-C Allow\sthe\srollback\sjournal\sto\sbe\sempty\sexcept\sfor\sits\sheader.\nTicket\s#212.\s(CVS\s809)
-D 2003-01-03T02:04:27
+C Optimizations\sto\sthe\sBTree\smodule\sfor\sa\smodest\sspeed\simprovement.\s(CVS\s810)
+D 2003-01-04T16:48:09
F Makefile.in 868c17a1ae1c07603d491274cc8f86c04acf2a1e
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
F publish.sh e5b83867d14708ed58cec8cba0a4f201e969474d
F spec.template 238f7db425a78dc1bb7682e56e3834c7270a3f5e
F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
-F src/btree.c 6a2a9bb701a60df4abe2fb7047b25787c90e1ffd
+F src/btree.c 4ed13ad0c695e4fb803d106926c6fdd08a0b4d0f
F src/btree.h 17710339f7a8f46e3c7d6d0d4648ef19c584ffda
F src/build.c 8569ac014609add4b796260d3567a5090b90056d
F src/delete.c aad9d4051ab46e6f6391ea5f7b8994a7c05bdd15
F test/select6.test efb8d0c07a440441db87db2c4ade6904e1407e85
F test/sort.test 876b76c5a837af5bead713146c7c65f85e84fbf5
F test/subselect.test f0fea8cf9f386d416d64d152e3c65f9116d0f50f
-F test/table.test 10508e5e53fb7971b9fa6acb29d85748e545745c
+F test/table.test 2a94f55b39008daa79b81f37aaf7be81386ca71e
F test/tableapi.test 3c80421a889e1d106df16e5800fa787f0d2914a6
F test/tclsqlite.test 2441ab135e5af85110326b3e3b057e7257c144e1
F test/temptable.test 03b7bdb7d6ce2c658ad20c94b037652c6cad34e0
F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P db745e87dc26cf1a35cdcec18f4b659742e14120
-R a2eb3af8e1d5fb0a64abc7b1644d24dd
+P 1ba41bc2afab18cc295d9a45845296b46bfa57e5
+R a4125fbf39c245763f99492b33c9c8e8
U drh
-Z 3fb10791064333a0f71d6fcfe3547d9c
+Z df8ce8a4e13ca11e4b128387a80bf533
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.76 2003/01/02 14:43:56 drh Exp $
+** $Id: btree.c,v 1.77 2003/01/04 16:48:09 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
char aDisk[SQLITE_PAGE_SIZE]; /* Page data stored on disk */
PageHdr hdr; /* Overlay page header */
} u;
- int isInit; /* True if auxiliary data is initialized */
+ u8 isInit; /* True if auxiliary data is initialized */
+ u8 idxShift; /* True if apCell[] indices have changed */
+ u8 isOverfull; /* Some apCell[] points outside u.aDisk[] */
MemPage *pParent; /* The parent of this page. NULL for root */
+ int idxParent; /* Index in pParent->apCell[] of this node */
int nFree; /* Number of free bytes in u.aDisk[] */
int nCell; /* Number of entries on this page */
- int isOverfull; /* Some apCell[] points outside u.aDisk[] */
Cell *apCell[MX_CELL+2]; /* All data entires in sorted order */
};
if( rc ) return rc;
rc = initPage(pBt, pNewPage, newPgno, pCur->pPage);
if( rc ) return rc;
+ assert( pCur->idx>=pCur->pPage->nCell
+ || pCur->pPage->apCell[pCur->idx]->h.leftChild==SWAB32(pBt,newPgno) );
+ assert( pCur->idx<pCur->pPage->nCell
+ || pCur->pPage->u.hdr.rightChild==SWAB32(pBt,newPgno) );
+ pNewPage->idxParent = pCur->idx;
+ pCur->pPage->idxShift = 0;
sqlitepager_unref(pCur->pPage);
pCur->pPage = pNewPage;
pCur->idx = 0;
static int moveToParent(BtCursor *pCur){
Pgno oldPgno;
MemPage *pParent;
- int i;
+ int idxParent;
pParent = pCur->pPage->pParent;
if( pParent==0 ) return SQLITE_INTERNAL;
+ idxParent = pCur->pPage->idxParent;
oldPgno = sqlitepager_pagenumber(pCur->pPage);
sqlitepager_ref(pParent);
sqlitepager_unref(pCur->pPage);
pCur->pPage = pParent;
- pCur->idx = pParent->nCell;
- oldPgno = SWAB32(pCur->pBt, oldPgno);
- for(i=0; i<pParent->nCell; i++){
- if( pParent->apCell[i]->h.leftChild==oldPgno ){
- pCur->idx = i;
- break;
+ assert( pParent->idxShift==0 );
+ if( pParent->idxShift==0 ){
+ pCur->idx = idxParent;
+#ifndef NDEBUG
+ /* Verify that pCur->idx is the correct index to point back to the child
+ ** page we just came from
+ */
+ oldPgno = SWAB32(pCur->pBt, oldPgno);
+ if( pCur->idx<pParent->nCell ){
+ assert( pParent->apCell[idxParent]->h.leftChild==oldPgno );
+ }else{
+ assert( pParent->u.hdr.rightChild==oldPgno );
+ }
+#endif
+ }else{
+ /* The MemPage.idxShift flag indicates that cell indices might have
+ ** changed since idxParent was set and hence idxParent might be out
+ ** of date. So recompute the parent cell index by scanning all cells
+ ** and locating the one that points to the child we just came from.
+ */
+ int i;
+ pCur->idx = pParent->nCell;
+ oldPgno = SWAB32(pCur->pBt, oldPgno);
+ for(i=0; i<pParent->nCell; i++){
+ if( pParent->apCell[i]->h.leftChild==oldPgno ){
+ pCur->idx = i;
+ break;
+ }
}
}
return SQLITE_OK;
int rc;
while( (pgno = pCur->pPage->u.hdr.rightChild)!=0 ){
+ pCur->idx = pCur->pPage->nCell;
rc = moveToChild(pCur, SWAB32(pCur->pBt, pgno));
if( rc ) return rc;
}
if( pRes ) *pRes = c;
return SQLITE_OK;
}
+ pCur->idx = lwr;
rc = moveToChild(pCur, SWAB32(pCur->pBt, chldPg));
if( rc ) return rc;
}
** given in the second argument so that MemPage.pParent holds the
** pointer in the third argument.
*/
-static void reparentPage(Pager *pPager, Pgno pgno, MemPage *pNewParent){
+static void reparentPage(Pager *pPager, Pgno pgno, MemPage *pNewParent,int idx){
MemPage *pThis;
if( pgno==0 ) return;
pThis->pParent = pNewParent;
if( pNewParent ) sqlitepager_ref(pNewParent);
}
+ pThis->idxParent = idx;
sqlitepager_unref(pThis);
}
}
int i;
Pager *pPager = pBt->pPager;
for(i=0; i<pPage->nCell; i++){
- reparentPage(pPager, SWAB32(pBt, pPage->apCell[i]->h.leftChild), pPage);
+ reparentPage(pPager, SWAB32(pBt, pPage->apCell[i]->h.leftChild), pPage, i);
}
- reparentPage(pPager, SWAB32(pBt, pPage->u.hdr.rightChild), pPage);
+ reparentPage(pPager, SWAB32(pBt, pPage->u.hdr.rightChild), pPage, i);
+ pPage->idxShift = 0;
}
/*
pPage->apCell[j] = pPage->apCell[j+1];
}
pPage->nCell--;
+ pPage->idxShift = 1;
}
/*
memcpy(&pPage->u.aDisk[idx], pCell, sz);
pPage->apCell[i] = (Cell*)&pPage->u.aDisk[idx];
}
+ pPage->idxShift = 1;
}
/*
assert( sqlitepager_iswriteable(pChild) );
copyPage(pChild, pPage);
pChild->pParent = pPage;
+ pChild->idxParent = pChild->nCell;
sqlitepager_ref(pPage);
pChild->isOverfull = 1;
if( pCur && pCur->pPage==pPage ){
if( idx<0 && pParent->u.hdr.rightChild==swabPgno ){
idx = pParent->nCell;
}
- if( idx<0 ){
- return SQLITE_CORRUPT;
- }
+ assert( idx>=0 );
+ /* assert( pParent->idxShift || idx==pPage->idxParent ); */
/*
** Initialize variables so that it will be safe to jump
if( rc ) goto balance_cleanup;
rc = initPage(pBt, apOld[i], pgnoOld[i], pParent);
if( rc ) goto balance_cleanup;
+ apOld[i]->idxParent = k;
nOld++;
}