diff options
Diffstat (limited to 'src/backend/access/gist/gistscan.c')
-rw-r--r-- | src/backend/access/gist/gistscan.c | 620 |
1 files changed, 328 insertions, 292 deletions
diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c index c877538472c..ec680558d88 100644 --- a/src/backend/access/gist/gistscan.c +++ b/src/backend/access/gist/gistscan.c @@ -1,11 +1,11 @@ /*------------------------------------------------------------------------- * * gistscan.c-- - * routines to manage scans on index relations + * routines to manage scans on index relations * * * IDENTIFICATION - * /usr/local/devel/pglite/cvs/src/backend/access/gist/gistscan.c,v 1.7 1995/06/14 00:10:05 jolly Exp + * /usr/local/devel/pglite/cvs/src/backend/access/gist/gistscan.c,v 1.7 1995/06/14 00:10:05 jolly Exp * *------------------------------------------------------------------------- */ @@ -18,375 +18,411 @@ #include <access/rtree.h> #include <storage/bufmgr.h> #include <access/giststrat.h> -#include <storage/lmgr.h> +#include <storage/lmgr.h> #ifndef HAVE_MEMMOVE -# include <regex/utils.h> +#include <regex/utils.h> #else -# include <string.h> +#include <string.h> #endif /* routines defined and used here */ -static void gistregscan(IndexScanDesc s); -static void gistdropscan(IndexScanDesc s); -static void gistadjone(IndexScanDesc s, int op, BlockNumber blkno, - OffsetNumber offnum); -static void adjuststack(GISTSTACK *stk, BlockNumber blkno, +static void gistregscan(IndexScanDesc s); +static void gistdropscan(IndexScanDesc s); +static void +gistadjone(IndexScanDesc s, int op, BlockNumber blkno, + OffsetNumber offnum); +static void +adjuststack(GISTSTACK * stk, BlockNumber blkno, OffsetNumber offnum); -static void adjustiptr(IndexScanDesc s, ItemPointer iptr, - int op, BlockNumber blkno, OffsetNumber offnum); +static void +adjustiptr(IndexScanDesc s, ItemPointer iptr, + int op, BlockNumber blkno, OffsetNumber offnum); /* - * Whenever we start a GiST scan in a backend, we register it in private - * space. Then if the GiST 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 GiST 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. + * Whenever we start a GiST scan in a backend, we register it in private + * space. Then if the GiST 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 GiST 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 GISTScanListData { - IndexScanDesc gsl_scan; - struct GISTScanListData *gsl_next; -} GISTScanListData; +typedef struct GISTScanListData +{ + IndexScanDesc gsl_scan; + struct GISTScanListData *gsl_next; +} GISTScanListData; -typedef GISTScanListData *GISTScanList; +typedef GISTScanListData *GISTScanList; /* pointer to list of local scans on GiSTs */ static GISTScanList GISTScans = (GISTScanList) NULL; - + IndexScanDesc gistbeginscan(Relation r, - bool fromEnd, - uint16 nkeys, - ScanKey key) + bool fromEnd, + uint16 nkeys, + ScanKey key) { - IndexScanDesc s; - - RelationSetLockForRead(r); - s = RelationGetIndexScan(r, fromEnd, nkeys, key); - gistregscan(s); - - return (s); + IndexScanDesc s; + + RelationSetLockForRead(r); + s = RelationGetIndexScan(r, fromEnd, nkeys, key); + gistregscan(s); + + return (s); } void gistrescan(IndexScanDesc s, bool fromEnd, ScanKey key) { - GISTScanOpaque p; - int i; - - if (!IndexScanIsValid(s)) { - elog(WARN, "gistrescan: invalid scan."); - return; - } - - /* - * Clear all the pointers. - */ - - ItemPointerSetInvalid(&s->previousItemData); - ItemPointerSetInvalid(&s->currentItemData); - ItemPointerSetInvalid(&s->nextItemData); - ItemPointerSetInvalid(&s->previousMarkData); - ItemPointerSetInvalid(&s->currentMarkData); - ItemPointerSetInvalid(&s->nextMarkData); - - /* - * Set flags. - */ - if (RelationGetNumberOfBlocks(s->relation) == 0) { - s->flags = ScanUnmarked; - } else if (fromEnd) { - s->flags = ScanUnmarked | ScanUncheckedPrevious; - } else { - s->flags = ScanUnmarked | ScanUncheckedNext; - } - - s->scanFromEnd = fromEnd; - - if (s->numberOfKeys > 0) { - memmove(s->keyData, - key, - s->numberOfKeys * sizeof(ScanKeyData)); - } - - p = (GISTScanOpaque) s->opaque; - if (p != (GISTScanOpaque) NULL) { - gistfreestack(p->s_stack); - gistfreestack(p->s_markstk); - p->s_stack = p->s_markstk = (GISTSTACK *) NULL; - p->s_flags = 0x0; - for (i = 0; i < s->numberOfKeys; i++) + GISTScanOpaque p; + int i; + + if (!IndexScanIsValid(s)) { - s->keyData[i].sk_procedure - = RelationGetGISTStrategy(s->relation, s->keyData[i].sk_attno, - s->keyData[i].sk_procedure); - s->keyData[i].sk_func = p->giststate->consistentFn; + elog(WARN, "gistrescan: invalid scan."); + return; + } + + /* + * Clear all the pointers. + */ + + ItemPointerSetInvalid(&s->previousItemData); + ItemPointerSetInvalid(&s->currentItemData); + ItemPointerSetInvalid(&s->nextItemData); + ItemPointerSetInvalid(&s->previousMarkData); + ItemPointerSetInvalid(&s->currentMarkData); + ItemPointerSetInvalid(&s->nextMarkData); + + /* + * Set flags. + */ + if (RelationGetNumberOfBlocks(s->relation) == 0) + { + s->flags = ScanUnmarked; + } + else if (fromEnd) + { + s->flags = ScanUnmarked | ScanUncheckedPrevious; + } + else + { + s->flags = ScanUnmarked | ScanUncheckedNext; + } + + s->scanFromEnd = fromEnd; + + if (s->numberOfKeys > 0) + { + memmove(s->keyData, + key, + s->numberOfKeys * sizeof(ScanKeyData)); + } + + p = (GISTScanOpaque) s->opaque; + if (p != (GISTScanOpaque) NULL) + { + gistfreestack(p->s_stack); + gistfreestack(p->s_markstk); + p->s_stack = p->s_markstk = (GISTSTACK *) NULL; + p->s_flags = 0x0; + for (i = 0; i < s->numberOfKeys; i++) + { + s->keyData[i].sk_procedure + = RelationGetGISTStrategy(s->relation, s->keyData[i].sk_attno, + s->keyData[i].sk_procedure); + s->keyData[i].sk_func = p->giststate->consistentFn; + } + } + else + { + /* initialize opaque data */ + p = (GISTScanOpaque) palloc(sizeof(GISTScanOpaqueData)); + p->s_stack = p->s_markstk = (GISTSTACK *) NULL; + p->s_flags = 0x0; + s->opaque = p; + p->giststate = (GISTSTATE *) palloc(sizeof(GISTSTATE)); + initGISTstate(p->giststate, s->relation); + if (s->numberOfKeys > 0) + + /* + * * Play games here with the scan key to use the Consistent * + * function for all comparisons: * 1) the sk_procedure field + * will now be used to hold the * strategy number * 2) the + * sk_func field will point to the Consistent function + */ + for (i = 0; i < s->numberOfKeys; i++) + { + + /* + * s->keyData[i].sk_procedure = + * index_getprocid(s->relation, 1, GIST_CONSISTENT_PROC); + */ + s->keyData[i].sk_procedure + = RelationGetGISTStrategy(s->relation, s->keyData[i].sk_attno, + s->keyData[i].sk_procedure); + s->keyData[i].sk_func = p->giststate->consistentFn; + } } - } else { - /* initialize opaque data */ - p = (GISTScanOpaque) palloc(sizeof(GISTScanOpaqueData)); - p->s_stack = p->s_markstk = (GISTSTACK *) NULL; - p->s_flags = 0x0; - s->opaque = p; - p->giststate = (GISTSTATE *)palloc(sizeof(GISTSTATE)); - initGISTstate(p->giststate, s->relation); - if (s->numberOfKeys > 0) - /* - ** Play games here with the scan key to use the Consistent - ** function for all comparisons: - ** 1) the sk_procedure field will now be used to hold the - ** strategy number - ** 2) the sk_func field will point to the Consistent function - */ - for (i = 0; i < s->numberOfKeys; i++) { - /* s->keyData[i].sk_procedure - = index_getprocid(s->relation, 1, GIST_CONSISTENT_PROC); */ - s->keyData[i].sk_procedure - = RelationGetGISTStrategy(s->relation, s->keyData[i].sk_attno, - s->keyData[i].sk_procedure); - s->keyData[i].sk_func = p->giststate->consistentFn; - } - } } void gistmarkpos(IndexScanDesc s) { - GISTScanOpaque p; - GISTSTACK *o, *n, *tmp; - - s->currentMarkData = s->currentItemData; - p = (GISTScanOpaque) s->opaque; - if (p->s_flags & GS_CURBEFORE) - p->s_flags |= GS_MRKBEFORE; - else - p->s_flags &= ~GS_MRKBEFORE; - - o = (GISTSTACK *) NULL; - n = p->s_stack; - - /* copy the parent stack from the current item data */ - while (n != (GISTSTACK *) NULL) { - tmp = (GISTSTACK *) palloc(sizeof(GISTSTACK)); - tmp->gs_child = n->gs_child; - tmp->gs_blk = n->gs_blk; - tmp->gs_parent = o; - o = tmp; - n = n->gs_parent; - } - - gistfreestack(p->s_markstk); - p->s_markstk = o; + GISTScanOpaque p; + GISTSTACK *o, + *n, + *tmp; + + s->currentMarkData = s->currentItemData; + p = (GISTScanOpaque) s->opaque; + if (p->s_flags & GS_CURBEFORE) + p->s_flags |= GS_MRKBEFORE; + else + p->s_flags &= ~GS_MRKBEFORE; + + o = (GISTSTACK *) NULL; + n = p->s_stack; + + /* copy the parent stack from the current item data */ + while (n != (GISTSTACK *) NULL) + { + tmp = (GISTSTACK *) palloc(sizeof(GISTSTACK)); + tmp->gs_child = n->gs_child; + tmp->gs_blk = n->gs_blk; + tmp->gs_parent = o; + o = tmp; + n = n->gs_parent; + } + + gistfreestack(p->s_markstk); + p->s_markstk = o; } void gistrestrpos(IndexScanDesc s) { - GISTScanOpaque p; - GISTSTACK *o, *n, *tmp; - - s->currentItemData = s->currentMarkData; - p = (GISTScanOpaque) s->opaque; - if (p->s_flags & GS_MRKBEFORE) - p->s_flags |= GS_CURBEFORE; - else - p->s_flags &= ~GS_CURBEFORE; - - o = (GISTSTACK *) NULL; - n = p->s_markstk; - - /* copy the parent stack from the current item data */ - while (n != (GISTSTACK *) NULL) { - tmp = (GISTSTACK *) palloc(sizeof(GISTSTACK)); - tmp->gs_child = n->gs_child; - tmp->gs_blk = n->gs_blk; - tmp->gs_parent = o; - o = tmp; - n = n->gs_parent; - } - - gistfreestack(p->s_stack); - p->s_stack = o; + GISTScanOpaque p; + GISTSTACK *o, + *n, + *tmp; + + s->currentItemData = s->currentMarkData; + p = (GISTScanOpaque) s->opaque; + if (p->s_flags & GS_MRKBEFORE) + p->s_flags |= GS_CURBEFORE; + else + p->s_flags &= ~GS_CURBEFORE; + + o = (GISTSTACK *) NULL; + n = p->s_markstk; + + /* copy the parent stack from the current item data */ + while (n != (GISTSTACK *) NULL) + { + tmp = (GISTSTACK *) palloc(sizeof(GISTSTACK)); + tmp->gs_child = n->gs_child; + tmp->gs_blk = n->gs_blk; + tmp->gs_parent = o; + o = tmp; + n = n->gs_parent; + } + + gistfreestack(p->s_stack); + p->s_stack = o; } void gistendscan(IndexScanDesc s) { - GISTScanOpaque p; - - p = (GISTScanOpaque) s->opaque; - - if (p != (GISTScanOpaque) NULL) { - gistfreestack(p->s_stack); - gistfreestack(p->s_markstk); - pfree (s->opaque); - } - - gistdropscan(s); - /* XXX don't unset read lock -- two-phase locking */ + GISTScanOpaque p; + + p = (GISTScanOpaque) s->opaque; + + if (p != (GISTScanOpaque) NULL) + { + gistfreestack(p->s_stack); + gistfreestack(p->s_markstk); + pfree(s->opaque); + } + + gistdropscan(s); + /* XXX don't unset read lock -- two-phase locking */ } static void gistregscan(IndexScanDesc s) { - GISTScanList l; - - l = (GISTScanList) palloc(sizeof(GISTScanListData)); - l->gsl_scan = s; - l->gsl_next = GISTScans; - GISTScans = l; + GISTScanList l; + + l = (GISTScanList) palloc(sizeof(GISTScanListData)); + l->gsl_scan = s; + l->gsl_next = GISTScans; + GISTScans = l; } static void gistdropscan(IndexScanDesc s) { - GISTScanList l; - GISTScanList prev; - - prev = (GISTScanList) NULL; - - for (l = GISTScans; - l != (GISTScanList) NULL && l->gsl_scan != s; - l = l->gsl_next) { - prev = l; - } - - if (l == (GISTScanList) NULL) - elog(WARN, "GiST scan list corrupted -- cannot find 0x%lx", s); - - if (prev == (GISTScanList) NULL) - GISTScans = l->gsl_next; - else - prev->gsl_next = l->gsl_next; - - pfree(l); + GISTScanList l; + GISTScanList prev; + + prev = (GISTScanList) NULL; + + for (l = GISTScans; + l != (GISTScanList) NULL && l->gsl_scan != s; + l = l->gsl_next) + { + prev = l; + } + + if (l == (GISTScanList) NULL) + elog(WARN, "GiST scan list corrupted -- cannot find 0x%lx", s); + + if (prev == (GISTScanList) NULL) + GISTScans = l->gsl_next; + else + prev->gsl_next = l->gsl_next; + + pfree(l); } void gistadjscans(Relation r, int op, BlockNumber blkno, OffsetNumber offnum) { - GISTScanList l; - Oid relid; - - relid = r->rd_id; - for (l = GISTScans; l != (GISTScanList) NULL; l = l->gsl_next) { - if (l->gsl_scan->relation->rd_id == relid) - gistadjone(l->gsl_scan, op, blkno, offnum); - } + GISTScanList l; + Oid relid; + + relid = r->rd_id; + for (l = GISTScans; l != (GISTScanList) NULL; l = l->gsl_next) + { + if (l->gsl_scan->relation->rd_id == relid) + gistadjone(l->gsl_scan, op, blkno, offnum); + } } /* - * gistadjone() -- adjust one scan for update. + * gistadjone() -- 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. + * 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 gistadjone(IndexScanDesc s, - int op, - BlockNumber blkno, - OffsetNumber offnum) + int op, + BlockNumber blkno, + OffsetNumber offnum) { - GISTScanOpaque so; - - adjustiptr(s, &(s->currentItemData), op, blkno, offnum); - adjustiptr(s, &(s->currentMarkData), op, blkno, offnum); - - so = (GISTScanOpaque) s->opaque; - - if (op == GISTOP_SPLIT) { - adjuststack(so->s_stack, blkno, offnum); - adjuststack(so->s_markstk, blkno, offnum); - } + GISTScanOpaque so; + + adjustiptr(s, &(s->currentItemData), op, blkno, offnum); + adjustiptr(s, &(s->currentMarkData), op, blkno, offnum); + + so = (GISTScanOpaque) s->opaque; + + if (op == GISTOP_SPLIT) + { + adjuststack(so->s_stack, blkno, offnum); + adjuststack(so->s_markstk, blkno, offnum); + } } /* - * adjustiptr() -- adjust current and marked item pointers in the scan + * 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. + * 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) + ItemPointer iptr, + int op, + BlockNumber blkno, + OffsetNumber offnum) { - OffsetNumber curoff; - GISTScanOpaque so; - - if (ItemPointerIsValid(iptr)) { - if (ItemPointerGetBlockNumber(iptr) == blkno) { - curoff = ItemPointerGetOffsetNumber(iptr); - so = (GISTScanOpaque) s->opaque; - - switch (op) { - case GISTOP_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 |= GS_CURBEFORE; - else - so->s_flags |= GS_MRKBEFORE; - } + OffsetNumber curoff; + GISTScanOpaque so; + + if (ItemPointerIsValid(iptr)) + { + if (ItemPointerGetBlockNumber(iptr) == blkno) + { + curoff = ItemPointerGetOffsetNumber(iptr); + so = (GISTScanOpaque) s->opaque; + + switch (op) + { + case GISTOP_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 |= GS_CURBEFORE; + else + so->s_flags |= GS_MRKBEFORE; + } + } + break; + + case GISTOP_SPLIT: + /* back to start of page on split */ + ItemPointerSet(iptr, blkno, FirstOffsetNumber); + if (iptr == &(s->currentItemData)) + so->s_flags &= ~GS_CURBEFORE; + else + so->s_flags &= ~GS_MRKBEFORE; + break; + + default: + elog(WARN, "Bad operation in GiST scan adjust: %d", op); + } } - break; - - case GISTOP_SPLIT: - /* back to start of page on split */ - ItemPointerSet(iptr, blkno, FirstOffsetNumber); - if (iptr == &(s->currentItemData)) - so->s_flags &= ~GS_CURBEFORE; - else - so->s_flags &= ~GS_MRKBEFORE; - break; - - default: - elog(WARN, "Bad operation in GiST scan adjust: %d", op); - } } - } } /* - * adjuststack() -- adjust the supplied stack for a split on a page in - * the index we're scanning. + * 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 GiSTs 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. + * 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 GiSTs 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. */ /*ARGSUSED*/ static void -adjuststack(GISTSTACK *stk, - BlockNumber blkno, - OffsetNumber offnum) +adjuststack(GISTSTACK * stk, + BlockNumber blkno, + OffsetNumber offnum) { - while (stk != (GISTSTACK *) NULL) { - if (stk->gs_blk == blkno) - stk->gs_child = FirstOffsetNumber; - - stk = stk->gs_parent; - } + while (stk != (GISTSTACK *) NULL) + { + if (stk->gs_blk == blkno) + stk->gs_child = FirstOffsetNumber; + + stk = stk->gs_parent; + } } |