@ -415,8 +415,7 @@ PageRestoreTempPage(Page tempPage, Page oldPage)
}
/*
* sorting support for PageRepairFragmentation , PageIndexMultiDelete ,
* PageIndexDeleteNoCompact
* sorting support for PageRepairFragmentation and PageIndexMultiDelete
*/
typedef struct itemIdSortData
{
@ -762,15 +761,14 @@ PageIndexTupleDelete(Page page, OffsetNumber offnum)
* Now move everything between the old upper bound ( beginning of tuple
* space ) and the beginning of the deleted tuple forward , so that space in
* the middle of the page is left free . If we ' ve just deleted the tuple
* at the beginning of tuple space , then there ' s no need to do the copy
* ( and bcopy on some architectures SEGV ' s if asked to move zero bytes ) .
* at the beginning of tuple space , then there ' s no need to do the copy .
*/
/* beginning of tuple space */
addr = ( char * ) page + phdr - > pd_upper ;
if ( offset > phdr - > pd_upper )
memmove ( addr + size , addr , ( int ) ( offset - phdr - > pd_upper ) ) ;
memmove ( addr + size , addr , offset - phdr - > pd_upper ) ;
/* adjust free space boundary pointers */
phdr - > pd_upper + = size ;
@ -918,155 +916,105 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
compactify_tuples ( itemidbase , nused , page ) ;
}
/*
* PageIndexDeleteNoCompact
* Delete the given items for an index page , and defragment the resulting
* free space , but do not compact the item pointers array .
*
* itemnos is the array of tuples to delete ; nitems is its size . maxIdxTuples
* is the maximum number of tuples that can exist in a page .
* PageIndexTupleDeleteNoCompact
*
* Unused items at the end of the array are removed .
* Remove the specified tuple from an index page , but set its line pointer
* to " unused " instead of compacting it out , except that it can be removed
* if it ' s the last line pointer on the page .
*
* This is used for index AMs that require that existing TIDs of live tuples
* remain unchanged .
* remain unchanged , and are willing to allow unused line pointers instead .
*/
void
PageIndexDeleteNoCompact ( Page page , OffsetNumber * itemnos , int nitems )
PageIndexTuple DeleteNoCompact ( Page page , OffsetNumber offnum )
{
PageHeader phdr = ( PageHeader ) page ;
LocationIndex pd_lower = phdr - > pd_lower ;
LocationIndex pd_upper = phdr - > pd_upper ;
LocationIndex pd_special = phdr - > pd_special ;
char * addr ;
ItemId tup ;
Size size ;
unsigned offset ;
int nline ;
bool empty ;
OffsetNumber offnum ;
int nextitm ;
/*
* As with PageRepairFragmentation , paranoia seems justified .
*/
if ( pd_lower < SizeOfPageHeaderData | |
pd_lower > pd_upper | |
pd_upper > pd_special | |
pd_special > BLCKSZ | |
pd_special ! = MAXALIGN ( pd_special ) )
if ( phdr - > p d_lower < SizeOfPageHeaderData | |
phdr - > p d_lower > phdr - > pd_upper | |
phdr - > p d_upper > phdr - > pd_special | |
phdr - > p d_special > BLCKSZ | |
phdr - > p d_special ! = MAXALIGN ( phdr - > pd_special ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATA_CORRUPTED ) ,
errmsg ( " corrupted page pointers: lower = %u, upper = %u, special = %u " ,
pd_lower , pd_upper , pd_special ) ) ) ;
phdr - > pd_lower , phdr - > pd_upper , phdr - > pd_special ) ) ) ;
nline = PageGetMaxOffsetNumber ( page ) ;
if ( ( int ) offnum < = 0 | | ( int ) offnum > nline )
elog ( ERROR , " invalid index offnum: %u " , offnum ) ;
tup = PageGetItemId ( page , offnum ) ;
Assert ( ItemIdHasStorage ( tup ) ) ;
size = ItemIdGetLength ( tup ) ;
offset = ItemIdGetOffset ( tup ) ;
if ( offset < phdr - > pd_upper | | ( offset + size ) > phdr - > pd_special | |
offset ! = MAXALIGN ( offset ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATA_CORRUPTED ) ,
errmsg ( " corrupted item pointer: offset = %u, size = %u " ,
offset , ( unsigned int ) size ) ) ) ;
/* Amount of space to actually be deleted */
size = MAXALIGN ( size ) ;
/*
* Scan the existing item pointer array and mark as unused those that are
* in our kill - list ; make sure any non - interesting ones are marked unused
* as well .
* Either set the item pointer to " unused " , or zap it if it ' s the last
* one . ( Note : it ' s possible that the next - to - last one ( s ) are already
* unused , but we do not trouble to try to compact them out if so . )
*/
nline = PageGetMaxOffsetNumber ( page ) ;
empty = true ;
nextitm = 0 ;
for ( offnum = FirstOffsetNumber ; offnum < = nline ; offnum = OffsetNumberNext ( offnum ) )
if ( ( int ) offnum < nline )
ItemIdSetUnused ( tup ) ;
else
{
ItemId lp ;
ItemLength itemlen ;
ItemOffset offset ;
phdr - > pd_lower - = sizeof ( ItemIdData ) ;
nline - - ; /* there's one less than when we started */
}
lp = PageGetItemId ( page , offnum ) ;
/*
* Now move everything between the old upper bound ( beginning of tuple
* space ) and the beginning of the deleted tuple forward , so that space in
* the middle of the page is left free . If we ' ve just deleted the tuple
* at the beginning of tuple space , then there ' s no need to do the copy .
*/
itemlen = ItemIdGetLength ( lp ) ;
offset = ItemIdGetOffset ( lp ) ;
/* beginning of tuple space */
addr = ( char * ) page + phdr - > pd_upper ;
if ( ItemIdIsUsed ( lp ) )
{
if ( offset < pd_upper | |
( offset + itemlen ) > pd_special | |
offset ! = MAXALIGN ( offset ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATA_CORRUPTED ) ,
errmsg ( " corrupted item pointer: offset = %u, length = %u " ,
offset , ( unsigned int ) itemlen ) ) ) ;
if ( nextitm < nitems & & offnum = = itemnos [ nextitm ] )
{
/* this one is on our list to delete, so mark it unused */
ItemIdSetUnused ( lp ) ;
nextitm + + ;
}
else if ( ItemIdHasStorage ( lp ) )
{
/* This one's live -- must do the compaction dance */
empty = false ;
}
else
{
/* get rid of this one too */
ItemIdSetUnused ( lp ) ;
}
}
}
if ( offset > phdr - > pd_upper )
memmove ( addr + size , addr , offset - phdr - > pd_upper ) ;
/* this will catch invalid or out-of-order itemnos[] */
if ( nextitm ! = nitems )
elog ( ERROR , " incorrect index offsets supplied " ) ;
/* adjust free space boundary pointer */
phdr - > pd_upper + = size ;
if ( empty )
{
/* Page is completely empty, so just reset it quickly */
phdr - > pd_lower = SizeOfPageHeaderData ;
phdr - > pd_upper = pd_special ;
}
els e
/*
* Finally , we need to adjust the linp entries that remain .
*
* Anything that used to be before the deleted tuple ' s data was moved
* forward by the size of the deleted tuple .
*/
if ( ! PageIsEmpty ( page ) )
{
/* There are live items: need to compact the page the hard way */
itemIdSortData itemidbase [ MaxOffsetNumber ] ;
itemIdSort itemidptr ;
int i ;
Size totallen ;
/*
* Scan the page taking note of each item that we need to preserve .
* This includes both live items ( those that contain data ) and
* interspersed unused ones . It ' s critical to preserve these unused
* items , because otherwise the offset numbers for later live items
* would change , which is not acceptable . Unused items might get used
* again later ; that is fine .
*/
itemidptr = itemidbase ;
totallen = 0 ;
PageClearHasFreeLinePointers ( page ) ;
for ( i = 0 ; i < nline ; i + + )
for ( i = 1 ; i < = nline ; i + + )
{
ItemId lp ;
itemidptr - > offsetindex = i ;
ItemId ii = PageGetItemId ( phdr , i ) ;
lp = PageGetItemId ( page , i + 1 ) ;
if ( ItemIdHasStorage ( lp ) )
{
itemidptr - > itemoff = ItemIdGetOffset ( lp ) ;
itemidptr - > alignedlen = MAXALIGN ( ItemIdGetLength ( lp ) ) ;
totallen + = itemidptr - > alignedlen ;
itemidptr + + ;
}
else
{
PageSetHasFreeLinePointers ( page ) ;
ItemIdSetUnused ( lp ) ;
}
if ( ItemIdHasStorage ( ii ) & & ItemIdGetOffset ( ii ) < = offset )
ii - > lp_off + = size ;
}
nline = itemidptr - itemidbase ;
/* By here, there are exactly nline elements in itemidbase array */
if ( totallen > ( Size ) ( pd_special - pd_lower ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATA_CORRUPTED ) ,
errmsg ( " corrupted item lengths: total %u, available space %u " ,
( unsigned int ) totallen , pd_special - pd_lower ) ) ) ;
/*
* Defragment the data areas of each tuple , being careful to preserve
* each item ' s position in the linp array .
*/
compactify_tuples ( itemidbase , nline , page ) ;
}
}