summaryrefslogtreecommitdiff
path: root/src/backend/access/gist/gistget.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/gist/gistget.c')
-rw-r--r--src/backend/access/gist/gistget.c190
1 files changed, 101 insertions, 89 deletions
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
index a1fd296dbf..97ae1cfd58 100644
--- a/src/backend/access/gist/gistget.c
+++ b/src/backend/access/gist/gistget.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.74 2008/06/19 00:46:03 alvherre Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.75 2008/08/23 10:37:24 teodor Exp $
*
*-------------------------------------------------------------------------
*/
@@ -32,63 +32,39 @@ static bool gistindex_keytest(IndexTuple tuple, IndexScanDesc scan,
static void
killtuple(Relation r, GISTScanOpaque so, ItemPointer iptr)
{
- Buffer buffer = so->curbuf;
-
- for (;;)
- {
- Page p;
- BlockNumber blkno;
- OffsetNumber offset,
- maxoff;
-
- LockBuffer(buffer, GIST_SHARE);
- gistcheckpage(r, buffer);
- p = (Page) BufferGetPage(buffer);
+ Page p;
+ OffsetNumber offset;
- if (buffer == so->curbuf && XLByteEQ(so->stack->lsn, PageGetLSN(p)))
- {
- /* page unchanged, so all is simple */
- offset = ItemPointerGetOffsetNumber(iptr);
- ItemIdMarkDead(PageGetItemId(p, offset));
- SetBufferCommitInfoNeedsSave(buffer);
- LockBuffer(buffer, GIST_UNLOCK);
- break;
- }
+ LockBuffer(so->curbuf, GIST_SHARE);
+ gistcheckpage(r, so->curbuf);
+ p = (Page) BufferGetPage(so->curbuf);
- maxoff = PageGetMaxOffsetNumber(p);
+ if (XLByteEQ(so->stack->lsn, PageGetLSN(p)))
+ {
+ /* page unchanged, so all is simple */
+ offset = ItemPointerGetOffsetNumber(iptr);
+ ItemIdMarkDead(PageGetItemId(p, offset));
+ SetBufferCommitInfoNeedsSave(so->curbuf);
+ }
+ else
+ {
+ OffsetNumber maxoff = PageGetMaxOffsetNumber(p);
for (offset = FirstOffsetNumber; offset <= maxoff; offset = OffsetNumberNext(offset))
{
- IndexTuple ituple = (IndexTuple) PageGetItem(p, PageGetItemId(p, offset));
+ IndexTuple ituple = (IndexTuple) PageGetItem(p, PageGetItemId(p, offset));
if (ItemPointerEquals(&(ituple->t_tid), iptr))
{
/* found */
ItemIdMarkDead(PageGetItemId(p, offset));
- SetBufferCommitInfoNeedsSave(buffer);
- LockBuffer(buffer, GIST_UNLOCK);
- if (buffer != so->curbuf)
- ReleaseBuffer(buffer);
- return;
+ SetBufferCommitInfoNeedsSave(so->curbuf);
+ break;
}
}
-
- /* follow right link */
-
- /*
- * ??? is it good? if tuple dropped by concurrent vacuum, we will read
- * all leaf pages...
- */
- blkno = GistPageGetOpaque(p)->rightlink;
- LockBuffer(buffer, GIST_UNLOCK);
- if (buffer != so->curbuf)
- ReleaseBuffer(buffer);
-
- if (blkno == InvalidBlockNumber)
- /* can't found, dropped by somebody else */
- return;
- buffer = ReadBuffer(r, blkno);
}
+
+ LockBuffer(so->curbuf, GIST_UNLOCK);
}
/*
@@ -154,7 +130,6 @@ gistnext(IndexScanDesc scan, ScanDirection dir, TIDBitmap *tbm)
GISTSearchStack *stk;
IndexTuple it;
GISTPageOpaque opaque;
- bool resetoffset = false;
int64 ntids = 0;
so = (GISTScanOpaque) scan->opaque;
@@ -179,6 +154,50 @@ gistnext(IndexScanDesc scan, ScanDirection dir, TIDBitmap *tbm)
return 0;
}
+ /*
+ * check stored pointers from last visit
+ */
+ if ( so->nPageData > 0 )
+ {
+ /*
+ * gistgetmulti never should go here
+ */
+ Assert( tbm == NULL );
+
+ if ( so->curPageData < so->nPageData )
+ {
+ /*
+ * pageData is already ordered for scan's direction
+ */
+ scan->xs_ctup.t_self = so->pageData[ so->curPageData ].iptr;
+ scan->xs_recheck = so->pageData[ so->curPageData ].recheck;
+ so->curPageData ++;
+
+ return 1;
+ }
+ else
+ {
+ /*
+ * Go to the next page
+ */
+ stk = so->stack->next;
+ pfree(so->stack);
+ so->stack = stk;
+
+ /* If we're out of stack entries, we're done */
+ if (so->stack == NULL)
+ {
+ ReleaseBuffer(so->curbuf);
+ so->curbuf = InvalidBuffer;
+ return 0;
+ }
+
+ so->curbuf = ReleaseAndReadBuffer(so->curbuf,
+ scan->indexRelation,
+ stk->block);
+ }
+ }
+
for (;;)
{
CHECK_FOR_INTERRUPTS();
@@ -189,30 +208,25 @@ gistnext(IndexScanDesc scan, ScanDirection dir, TIDBitmap *tbm)
gistcheckpage(scan->indexRelation, so->curbuf);
p = BufferGetPage(so->curbuf);
opaque = GistPageGetOpaque(p);
- resetoffset = false;
- if (XLogRecPtrIsInvalid(so->stack->lsn) || !XLByteEQ(so->stack->lsn, PageGetLSN(p)))
- {
- /* first visit or page changed from last visit, reset offset */
- so->stack->lsn = PageGetLSN(p);
- resetoffset = true;
-
- /* check page split, occured from last visit or visit to parent */
- if (!XLogRecPtrIsInvalid(so->stack->parentlsn) &&
- XLByteLT(so->stack->parentlsn, opaque->nsn) &&
- opaque->rightlink != InvalidBlockNumber /* sanity check */ &&
- (so->stack->next == NULL || so->stack->next->block != opaque->rightlink) /* check if already
- added */ )
- {
- /* detect page split, follow right link to add pages */
+ /* remember lsn to identify page changed for tuple's killing */
+ so->stack->lsn = PageGetLSN(p);
- stk = (GISTSearchStack *) palloc(sizeof(GISTSearchStack));
- stk->next = so->stack->next;
- stk->block = opaque->rightlink;
- stk->parentlsn = so->stack->parentlsn;
- memset(&(stk->lsn), 0, sizeof(GistNSN));
- so->stack->next = stk;
- }
+ /* check page split, occured since visit to parent */
+ if (!XLogRecPtrIsInvalid(so->stack->parentlsn) &&
+ XLByteLT(so->stack->parentlsn, opaque->nsn) &&
+ opaque->rightlink != InvalidBlockNumber /* sanity check */ &&
+ (so->stack->next == NULL || so->stack->next->block != opaque->rightlink) /* check if already
+ added */ )
+ {
+ /* detect page split, follow right link to add pages */
+
+ stk = (GISTSearchStack *) palloc(sizeof(GISTSearchStack));
+ stk->next = so->stack->next;
+ stk->block = opaque->rightlink;
+ stk->parentlsn = so->stack->parentlsn;
+ memset(&(stk->lsn), 0, sizeof(GistNSN));
+ so->stack->next = stk;
}
/* if page is empty, then just skip it */
@@ -235,25 +249,13 @@ gistnext(IndexScanDesc scan, ScanDirection dir, TIDBitmap *tbm)
continue;
}
- if (!GistPageIsLeaf(p) || resetoffset ||
- !ItemPointerIsValid(&so->curpos))
- {
- if (ScanDirectionIsBackward(dir))
- n = PageGetMaxOffsetNumber(p);
- else
- n = FirstOffsetNumber;
- }
+ if (ScanDirectionIsBackward(dir))
+ n = PageGetMaxOffsetNumber(p);
else
- {
- n = ItemPointerGetOffsetNumber(&(so->curpos));
-
- if (ScanDirectionIsBackward(dir))
- n = OffsetNumberPrev(n);
- else
- n = OffsetNumberNext(n);
- }
+ n = FirstOffsetNumber;
/* wonderful, we can look at page */
+ so->nPageData = so->curPageData = 0;
for (;;)
{
@@ -262,6 +264,18 @@ gistnext(IndexScanDesc scan, ScanDirection dir, TIDBitmap *tbm)
if (!OffsetNumberIsValid(n))
{
/*
+ * If we was called from gistgettuple and current buffer contains
+ * something matched then make a recursive call - it will return
+ * ItemPointer from so->pageData. But we save buffer pinned to
+ * support tuple's killing
+ */
+ if ( !tbm && so->nPageData > 0 )
+ {
+ LockBuffer(so->curbuf, GIST_UNLOCK);
+ return gistnext(scan, dir, NULL);
+ }
+
+ /*
* We ran out of matching index entries on the current page,
* so pop the top stack entry and use it to continue the
* search.
@@ -306,11 +320,9 @@ gistnext(IndexScanDesc scan, ScanDirection dir, TIDBitmap *tbm)
tbm_add_tuples(tbm, &it->t_tid, 1, scan->xs_recheck);
else
{
- scan->xs_ctup.t_self = it->t_tid;
- /* scan->xs_recheck is already set */
-
- LockBuffer(so->curbuf, GIST_UNLOCK);
- return ntids; /* always 1 */
+ so->pageData[ so->nPageData ].iptr = it->t_tid;
+ so->pageData[ so->nPageData ].recheck = scan->xs_recheck;
+ so->nPageData ++;
}
}
}