@ -8,7 +8,7 @@
* Portions Copyright ( c ) 1994 , Regents of the University of California
* Portions Copyright ( c ) 1994 , Regents of the University of California
*
*
* IDENTIFICATION
* IDENTIFICATION
* $ PostgreSQL : pgsql / src / backend / access / gist / gistget . c , v 1.52 .2 .1 2005 / 11 / 22 18 : 23 : 03 momjian Exp $
* $ PostgreSQL : pgsql / src / backend / access / gist / gistget . c , v 1.52 .2 .2 2008 / 08 / 23 10 : 43 : 58 teodor Exp $
*
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
*/
@ -30,62 +30,38 @@ static bool gistindex_keytest(IndexTuple tuple, IndexScanDesc scan,
static void
static void
killtuple ( Relation r , GISTScanOpaque so , ItemPointer iptr )
killtuple ( Relation r , GISTScanOpaque so , ItemPointer iptr )
{
{
Buffer buffer = so - > curbuf ;
Page p ;
OffsetNumber offset ;
for ( ; ; )
LockBuffer ( so - > curbuf , GIST_SHARE ) ;
p = ( Page ) BufferGetPage ( so - > curbuf ) ;
if ( XLByteEQ ( so - > stack - > lsn , PageGetLSN ( p ) ) )
{
{
Page p ;
/* page unchanged, so all is simple */
BlockNumber blkno ;
offset = ItemPointerGetOffsetNumber ( iptr ) ;
OffsetNumber offset ,
PageGetItemId ( p , offset ) - > lp_flags | = LP_DELETE ;
maxoff ;
SetBufferCommitInfoNeedsSave ( so - > curbuf ) ;
}
LockBuffer ( buffer , GIST_SHARE ) ;
else
p = ( Page ) BufferGetPage ( buffer ) ;
{
OffsetNumber maxoff = PageGetMaxOffsetNumber ( p ) ;
if ( buffer = = so - > curbuf & & XLByteEQ ( so - > stack - > lsn , PageGetLSN ( p ) ) )
{
/* page unchanged, so all is simple */
offset = ItemPointerGetOffsetNumber ( iptr ) ;
PageGetItemId ( p , offset ) - > lp_flags | = LP_DELETE ;
SetBufferCommitInfoNeedsSave ( buffer ) ;
LockBuffer ( buffer , GIST_UNLOCK ) ;
break ;
}
maxoff = PageGetMaxOffsetNumber ( p ) ;
for ( offset = FirstOffsetNumber ; offset < = maxoff ; offset = OffsetNumberNext ( offset ) )
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 ) )
if ( ItemPointerEquals ( & ( ituple - > t_tid ) , iptr ) )
{
{
/* found */
/* found */
PageGetItemId ( p , offset ) - > lp_flags | = LP_DELETE ;
PageGetItemId ( p , offset ) - > lp_flags | = LP_DELETE ;
SetBufferCommitInfoNeedsSave ( buffer ) ;
SetBufferCommitInfoNeedsSave ( so - > curbuf ) ;
LockBuffer ( buffer , GIST_UNLOCK ) ;
break ;
if ( buffer ! = so - > curbuf )
ReleaseBuffer ( buffer ) ;
return ;
}
}
}
}
/* 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 ) ;
}
}
/*
/*
@ -146,7 +122,6 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b
GISTSearchStack * stk ;
GISTSearchStack * stk ;
IndexTuple it ;
IndexTuple it ;
GISTPageOpaque opaque ;
GISTPageOpaque opaque ;
bool resetoffset = false ;
int ntids = 0 ;
int ntids = 0 ;
so = ( GISTScanOpaque ) scan - > opaque ;
so = ( GISTScanOpaque ) scan - > opaque ;
@ -171,6 +146,42 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b
return 0 ;
return 0 ;
}
}
/*
* check stored pointers from last visit
*/
if ( so - > nPageData > 0 )
{
while ( ntids < maxtids & & so - > curPageData < so - > nPageData )
{
tids [ ntids ] = scan - > xs_ctup . t_self = so - > pageData [ so - > curPageData ] ;
so - > curPageData + + ;
ntids + + ;
}
if ( ntids = = maxtids )
return ntids ;
/*
* 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 ntids ;
}
so - > curbuf = ReleaseAndReadBuffer ( so - > curbuf ,
scan - > indexRelation ,
stk - > block ) ;
}
for ( ; ; )
for ( ; ; )
{
{
/* First of all, we need lock buffer */
/* First of all, we need lock buffer */
@ -178,30 +189,25 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b
LockBuffer ( so - > curbuf , GIST_SHARE ) ;
LockBuffer ( so - > curbuf , GIST_SHARE ) ;
p = BufferGetPage ( so - > curbuf ) ;
p = BufferGetPage ( so - > curbuf ) ;
opaque = GistPageGetOpaque ( p ) ;
opaque = GistPageGetOpaque ( p ) ;
resetoffset = false ;
if ( XLogRecPtrIsInvalid ( so - > stack - > lsn ) | | ! XLByteEQ ( so - > stack - > lsn , PageGetLSN ( p ) ) )
/* remember lsn to identify page changed for tuple's killing */
{
so - > stack - > lsn = PageGetLSN ( p ) ;
/* page changed from last visit or visit first time , 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 */
stk = ( GISTSearchStack * ) palloc ( sizeof ( GISTSearchStack ) ) ;
/* check page split, occured from last visit or visit to parent */
stk - > next = so - > stack - > next ;
if ( ! XLogRecPtrIsInvalid ( so - > stack - > parentlsn ) & &
stk - > block = opaque - > rightlink ;
XLByteLT ( so - > stack - > parentlsn , opaque - > nsn ) & &
stk - > parentlsn = so - > stack - > parentlsn ;
opaque - > rightlink ! = InvalidBlockNumber /* sanity check */ & &
memset ( & ( stk - > lsn ) , 0 , sizeof ( GistNSN ) ) ;
( so - > stack - > next = = NULL | | so - > stack - > next - > block ! = opaque - > rightlink ) /* check if already
so - > stack - > next = stk ;
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 */
/* if page is empty, then just skip it */
@ -224,24 +230,13 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b
continue ;
continue ;
}
}
if ( ! GistPageIsLeaf ( p ) | | resetoffset | | ItemPointerIsValid ( & scan - > currentItemData ) = = false )
if ( ScanDirectionIsBackward ( dir ) )
{
n = PageGetMaxOffsetNumber ( p ) ;
if ( ScanDirectionIsBackward ( dir ) )
n = PageGetMaxOffsetNumber ( p ) ;
else
n = FirstOffsetNumber ;
}
else
else
{
n = FirstOffsetNumber ;
n = ItemPointerGetOffsetNumber ( & ( scan - > currentItemData ) ) ;
if ( ScanDirectionIsBackward ( dir ) )
n = OffsetNumberPrev ( n ) ;
else
n = OffsetNumberNext ( n ) ;
}
/* wonderfull, we can look at page */
/* wonderfull, we can look at page */
so - > nPageData = so - > curPageData = 0 ;
for ( ; ; )
for ( ; ; )
{
{
@ -249,6 +244,20 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b
if ( ! OffsetNumberIsValid ( n ) )
if ( ! OffsetNumberIsValid ( n ) )
{
{
while ( ntids < maxtids & & so - > curPageData < so - > nPageData )
{
tids [ ntids ] = scan - > xs_ctup . t_self = so - > pageData [ so - > curPageData ] ;
so - > curPageData + + ;
ntids + + ;
}
if ( ntids = = maxtids )
{
LockBuffer ( so - > curbuf , GIST_UNLOCK ) ;
return ntids ;
}
/*
/*
* We ran out of matching index entries on the current page ,
* We ran out of matching index entries on the current page ,
* so pop the top stack entry and use it to continue the
* so pop the top stack entry and use it to continue the
@ -288,14 +297,8 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b
if ( ! ( ignore_killed_tuples & & ItemIdDeleted ( PageGetItemId ( p , n ) ) ) )
if ( ! ( ignore_killed_tuples & & ItemIdDeleted ( PageGetItemId ( p , n ) ) ) )
{
{
it = ( IndexTuple ) PageGetItem ( p , PageGetItemId ( p , n ) ) ;
it = ( IndexTuple ) PageGetItem ( p , PageGetItemId ( p , n ) ) ;
tids [ ntids ] = scan - > xs_ctup . t_self = it - > t_tid ;
so - > pageData [ so - > nPageData ] = it - > t_tid ;
ntids + + ;
so - > nPageData + + ;
if ( ntids = = maxtids )
{
LockBuffer ( so - > curbuf , GIST_UNLOCK ) ;
return ntids ;
}
}
}
}
}
else
else