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.518 2008/09/29 11:49:48 danielk1977 Exp $ +** $Id: btree.c,v 1.519 2008/09/29 15:53:26 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. ** Including a description of file format and an overview of operation. */ @@ -942,11 +942,10 @@ data = pPage->aData; if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT; assert( pBt->pageSize>=512 && pBt->pageSize<=32768 ); pPage->maskPage = pBt->pageSize - 1; pPage->nOverflow = 0; - pPage->idxShift = 0; usableSize = pBt->usableSize; pPage->cellOffset = cellOffset = hdr + 12 - 4*pPage->leaf; top = get2byte(&data[hdr+5]); pPage->nCell = get2byte(&data[hdr+3]); if( pPage->nCell>MX_CELL(pBt) ){ @@ -1029,11 +1028,10 @@ pPage->hdrOffset = hdr; pPage->cellOffset = first; pPage->nOverflow = 0; assert( pBt->pageSize>=512 && pBt->pageSize<=32768 ); pPage->maskPage = pBt->pageSize - 1; - pPage->idxShift = 0; pPage->nCell = 0; pPage->isInit = 1; } @@ -3441,11 +3439,10 @@ if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){ return SQLITE_CORRUPT_BKPT; } rc = getAndInitPage(pBt, newPgno, &pNewPage); if( rc ) return rc; - pCur->apPage[i]->idxShift = 0; pCur->apPage[i+1] = pNewPage; pCur->aiIdx[i+1] = 0; pCur->iPage++; pCur->info.nSize = 0; @@ -3453,10 +3450,30 @@ if( pNewPage->nCell<1 ){ return SQLITE_CORRUPT_BKPT; } return SQLITE_OK; } + +#ifndef NDEBUG +/* +** Page pParent is an internal (non-leaf) tree page. This function +** asserts that page number iChild is the left-child if the iIdx'th +** cell in page pParent. Or, if iIdx is equal to the total number of +** cells in pParent, that page number iChild is the right-child of +** the page. +*/ +static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){ + assert( iIdx<=pParent->nCell ); + if( iIdx==pParent->nCell ){ + assert( get4byte(&pParent->aData[pParent->hdrOffset+8])==iChild ); + }else{ + assert( get4byte(findCell(pParent, iIdx))==iChild ); + } +} +#else +# define assertParentIndex(x,y,z) +#endif /* ** Move the cursor up to the parent page. ** ** pCur->idx is set to the cell index that contains the pointer @@ -3467,16 +3484,19 @@ void sqlite3BtreeMoveToParent(BtCursor *pCur){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->iPage>0 ); assert( pCur->apPage[pCur->iPage] ); - + assertParentIndex( + pCur->apPage[pCur->iPage-1], + pCur->aiIdx[pCur->iPage-1], + pCur->apPage[pCur->iPage]->pgno + ); releasePage(pCur->apPage[pCur->iPage]); pCur->iPage--; pCur->info.nSize = 0; pCur->validNKey = 0; - assert( pCur->apPage[pCur->iPage]->idxShift==0 ); } /* ** Move the cursor to the root page */ @@ -4587,11 +4607,10 @@ u8 *pCell = findCell(pPage, i); rc = reparentPage(pBt, get4byte(pCell), pPage, i, updatePtrmap); if( rc!=SQLITE_OK ) return rc; } rc = reparentPage(pBt, iRight, pPage, i, updatePtrmap); - pPage->idxShift = 0; } return rc; } /* @@ -4622,11 +4641,10 @@ ptr[1] = ptr[3]; } pPage->nCell--; put2byte(&data[pPage->hdrOffset+3], pPage->nCell); pPage->nFree += 2; - pPage->idxShift = 1; } /* ** Insert a new cell on pPage at cell index "i". pCell points to the ** content of the cell. @@ -4702,11 +4720,10 @@ ptr[0] = ptr[-2]; ptr[1] = ptr[-1]; } put2byte(&data[ins], idx); put2byte(&data[hdr+3], pPage->nCell); - pPage->idxShift = 1; #ifndef SQLITE_OMIT_AUTOVACUUM if( pPage->pBt->autoVacuum ){ /* The cell may contain a pointer to an overflow page. If so, write ** the entry for the overflow page into the pointer map. */ @@ -4831,16 +4848,10 @@ szCell = cellSizePtr(pPage, pCell); zeroPage(pNew, pPage->aData[0]); assemblePage(pNew, 1, &pCell, &szCell); pPage->nOverflow = 0; - /* Set the parent of the newly allocated page to pParent. */ -#if 0 - pNew->pParent = pParent; - sqlite3PagerRef(pParent->pDbPage); -#endif - /* pPage is currently the right-child of pParent. Change this ** so that the right-child is the new page allocated above and ** pPage is the next-to-right child. ** ** Ignore the return value of the call to fillInCell(). fillInCell() @@ -5021,31 +5032,18 @@ /* ** Find the cell in the parent page whose left child points back ** to pPage. The "idx" variable is the index of that cell. If pPage ** is the rightmost child of pParent then set idx to pParent->nCell */ - if( pParent->idxShift ){ - Pgno pgno; - pgno = pPage->pgno; - assert( pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); - for(idx=0; idxnCell; idx++){ - if( get4byte(findCell(pParent, idx))==pgno ){ - break; - } - } - assert( idxnCell - || get4byte(&pParent->aData[pParent->hdrOffset+8])==pgno ); - }else{ - idx = pCur->aiIdx[pCur->iPage-1]; - } + idx = pCur->aiIdx[pCur->iPage-1]; + assertParentIndex(pParent, idx, pPage->pgno); /* ** Initialize variables so that it will be safe to jump ** directly to balance_cleanup at any moment. */ nOld = nNew = 0; - /* sqlite3PagerRef(pParent->pDbPage); */ /* ** Find sibling pages to pPage and the cells in pParent that divide ** the siblings. An attempt is made to find NN siblings on either ** side of pPage. More siblings are taken from one side, however, if @@ -5730,10 +5728,11 @@ } if( rc==SQLITE_OK ){ pCur->iPage++; pCur->apPage[1] = pChild; + pCur->aiIdx[0] = 0; rc = balance_nonroot(pCur); }else{ releasePage(pChild); } Index: src/btreeInt.h ================================================================== --- src/btreeInt.h +++ src/btreeInt.h @@ -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: btreeInt.h,v 1.32 2008/09/29 11:49:48 danielk1977 Exp $ +** $Id: btreeInt.h,v 1.33 2008/09/29 15:53:26 danielk1977 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: @@ -269,11 +269,10 @@ ** Access to all fields of this structure is controlled by the mutex ** stored in MemPage.pBt->mutex. */ struct MemPage { u8 isInit; /* True if previously initialized. MUST BE FIRST! */ - u8 idxShift; /* True if Cell indices have changed */ u8 nOverflow; /* Number of overflow cell bodies in aCell[] */ u8 intKey; /* True if intkey flag is set */ u8 leaf; /* True if leaf flag is set */ u8 hasData; /* True if this page stores data */ u8 hdrOffset; /* 100 for page 1. 0 otherwise */