1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Fix an auto-vacuum bug for btree entries that span more than one overflow page. (CVS 2039)

FossilOrigin-Name: 40249ed19cd53cb61f9575d8165316faf2627479
This commit is contained in:
danielk1977
2004-11-02 14:40:32 +00:00
parent 06f502170e
commit f78fc0818c
4 changed files with 28 additions and 17 deletions

View File

@@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.197 2004/11/02 14:24:34 drh Exp $
** $Id: btree.c,v 1.198 2004/11/02 14:40:32 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
@@ -1564,8 +1564,9 @@ set_child_ptrmaps_out:
static void modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
if( eType==PTRMAP_OVERFLOW2 ){
/* The pointer is always the first 4 bytes of the page in this case. */
assert( get4byte(pPage->aData)==iFrom );
put4byte(pPage->aData, iFrom);
put4byte(pPage->aData, iTo);
}else{
int isInitOrig = pPage->isInit;
int i;
@@ -1574,8 +1575,6 @@ static void modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
initPage(pPage, 0);
nCell = pPage->nCell;
/* assert( !pPage->leaf && eType==PTRMAP_BTREE ); */
for(i=0; i<nCell; i++){
u8 *pCell = findCell(pPage, i);
if( eType==PTRMAP_OVERFLOW1 ){
@@ -1695,8 +1694,8 @@ static int autoVacuumCommit(Btree *pBt){
}while( iFreePage>finDbSize );
/* Move page iDbPage from it's current location to page number iFreePage */
TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d)\n",
iDbPage, iFreePage, iPtrPage));
TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n",
iDbPage, iFreePage, iPtrPage, eType));
releasePage(pFreeMemPage);
pFreeMemPage = 0;
rc = sqlite3pager_movepage(pPager, pDbPage, iFreePage);
@@ -1706,10 +1705,21 @@ static int autoVacuumCommit(Btree *pBt){
/* If pDbPage was a btree-page, then it may have child pages and/or cells
** that point to overflow pages. The pointer map entries for all these
** pages need to be changed.
**
** If pDbPage is an overflow page, then the first 4 bytes may store a
** pointer to a subsequent overflow page. If this is the case, then
** the pointer map needs to be updated for the subsequent overflow page.
*/
if( eType==PTRMAP_BTREE ){
rc = setChildPtrmaps(pDbMemPage);
if( rc!=SQLITE_OK ) goto autovacuum_out;
}else{
Pgno nextOvfl = get4byte(pDbPage);
if( nextOvfl!=0 ){
assert( nextOvfl<=origDbSize );
rc = ptrmapPut(pBt, nextOvfl, PTRMAP_OVERFLOW2, iFreePage);
if( rc!=SQLITE_OK ) goto autovacuum_out;
}
}
releasePage(pDbMemPage);
pDbMemPage = 0;