Index: src/btree.c ================================================================== --- src/btree.c +++ src/btree.c @@ -7,11 +7,11 @@ ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.337 2007/03/06 11:42:19 drh Exp $ +** $Id: btree.c,v 1.338 2007/03/06 15:53:44 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: @@ -363,10 +363,11 @@ typedef struct CellInfo CellInfo; struct CellInfo { u8 *pCell; /* Pointer to the start of cell content */ i64 nKey; /* The key for INTKEY tables, or number of bytes in key */ u32 nData; /* Number of bytes of data */ + u32 nPayload; /* Total amount of payload */ u16 nHeader; /* Size of the cell content header in bytes */ u16 nLocal; /* Amount of payload held locally */ u16 iOverflow; /* Offset to overflow page number. Zero if no overflow */ u16 nSize; /* Size of the cell content on the main b-tree page */ }; @@ -942,10 +943,11 @@ u32 x; n += getVarint32(&pCell[n], &x); pInfo->nKey = x; nPayload += x; } + pInfo->nPayload = nPayload; pInfo->nHeader = n; if( nPayload<=pPage->maxLocal ){ /* This is the (easy) common case where the entire payload fits ** on the local page. No overflow is required. */ @@ -1018,10 +1020,11 @@ */ static int ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell){ if( pCell ){ CellInfo info; parseCellPtr(pPage, pCell, &info); + assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload ); if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){ Pgno ovfl = get4byte(&pCell[info.iOverflow]); return ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno); } } @@ -3874,34 +3877,33 @@ CellInfo info; Pgno ovflPgno; int rc; int nOvfl; int ovflPageSize; - int nPayload; parseCellPtr(pPage, pCell, &info); if( info.iOverflow==0 ){ return SQLITE_OK; /* No overflow pages. Return without doing anything */ } ovflPgno = get4byte(&pCell[info.iOverflow]); - nPayload = pPage->intKey ? info.nData : info.nKey; ovflPageSize = pBt->usableSize - 4; - nOvfl = (nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize; - while( ovflPgno!=0 ){ + nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize; + assert( ovflPgno==0 || nOvfl>0 ); + while( nOvfl-- ){ MemPage *pOvfl; - nOvfl--; - if( ovflPgno>sqlite3pager_pagecount(pBt->pPager) ){ + if( ovflPgno==0 || ovflPgno>sqlite3pager_pagecount(pBt->pPager) ){ return SQLITE_CORRUPT_BKPT; } - rc = getPage(pBt, ovflPgno, &pOvfl, nOvfl==0); + rc = getPage(pBt, ovflPgno, &pOvfl, 0); if( rc ) return rc; - ovflPgno = get4byte(pOvfl->aData); + if( nOvfl ){ + ovflPgno = get4byte(pOvfl->aData); + } rc = freePage(pOvfl); sqlite3pager_unref(pOvfl->aData); if( rc ) return rc; } - assert( nOvfl==0 ); return SQLITE_OK; } /* ** Create the byte sequence used to represent a cell on page pPage @@ -4194,10 +4196,11 @@ /* The cell may contain a pointer to an overflow page. If so, write ** the entry for the overflow page into the pointer map. */ CellInfo info; parseCellPtr(pPage, pCell, &info); + assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload ); if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){ Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]); int rc = ptrmapPut(pPage->pBt, pgnoOvfl, PTRMAP_OVERFLOW1, pPage->pgno); if( rc!=SQLITE_OK ) return rc; } @@ -6199,10 +6202,11 @@ sprintf(zContext, "On tree page %d cell %d: ", iPage, i); pCell = findCell(pPage,i); parseCellPtr(pPage, pCell, &info); sz = info.nData; if( !pPage->intKey ) sz += info.nKey; + assert( sz==info.nPayload ); if( sz>info.nLocal ){ int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4); Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]); #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum ){