From a2c20e433b0bfe5135f446667e62db321906602a Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 29 Mar 2008 16:01:04 +0000 Subject: [PATCH] Make the sqlite3BtreeMoveto routine a no-op if the cursor is already pointing at the cell we are trying to move to. (CVS 4938) FossilOrigin-Name: 9b567ab61e7542141b7bc9c3c053c2d1180da92d --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/btree.c | 36 ++++++++++++++++++++++++++++++++++-- src/btreeInt.h | 4 +++- 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index c7c403f5b4..0261407548 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C add\stwo\smissing\sinitializer\svalues\s(CVS\s4937) -D 2008-03-29T12:50:33 +C Make\sthe\ssqlite3BtreeMoveto\sroutine\sa\sno-op\sif\sthe\scursor\sis\salready\spointing\nat\sthe\scell\swe\sare\strying\sto\smove\sto.\s(CVS\s4938) +D 2008-03-29T16:01:04 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in cf434ce8ca902e69126ae0f94fc9f7dc7428a5fa F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -86,9 +86,9 @@ F src/attach.c bdc75e759ca25a16f4dc7fbdbc6d37ad2561bb24 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627 F src/bitvec.c 49817d442e51e4123585f3cf3c2afc293a3c91e2 F src/btmutex.c 483ced3c52205b04b97df69161fadbf87f4f1ea2 -F src/btree.c 6e60d634d236232efbb289b800dd76e72a5ecf9d +F src/btree.c 20d51e14297a249408d9cc4bea433e23a72ef125 F src/btree.h c66cb17c6fffa84a88926dbef173bab4ae692fd4 -F src/btreeInt.h d232be68a7ab2a24376dc6332a869e717551b0bd +F src/btreeInt.h 8a2718652ed9413dc6acbb02a5c5a23a35a6e983 F src/build.c 4e6321d112f0ed1070c579677573e4eb76cda1fd F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0 F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131 @@ -619,7 +619,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P d6a34d983e2181f1d1763bd3821a1e63f1e18818 -R 205889753b1d77cef56f1f56cb8995e0 -U rse -Z a5f43d0478b1df89fabbb68795899e63 +P bf28f1c260b3efbec3b031edb97ccb7b4b039947 +R d9c5da155dc2408c6037314f48ac3576 +U drh +Z c9db9f5c48d0f08888b8f4af1ebe4788 diff --git a/manifest.uuid b/manifest.uuid index dfcee67bea..dffcaadbd9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bf28f1c260b3efbec3b031edb97ccb7b4b039947 \ No newline at end of file +9b567ab61e7542141b7bc9c3c053c2d1180da92d \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index b889096a65..2f14070622 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.447 2008/03/25 17:23:33 drh Exp $ +** $Id: btree.c,v 1.448 2008/03/29 16:01:04 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. @@ -2847,6 +2847,7 @@ void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){ static void getCellInfo(BtCursor *pCur){ if( pCur->info.nSize==0 ){ sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &pCur->info); + pCur->validNKey = 1; }else{ assertCellInfo(pCur); } @@ -2856,6 +2857,7 @@ void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){ #define getCellInfo(pCur) \ if( pCur->info.nSize==0 ){ \ sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &pCur->info); \ + pCur->validNKey = 1; \ }else{ \ assertCellInfo(pCur); \ } @@ -3349,6 +3351,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){ pCur->pPage = pNewPage; pCur->idx = 0; pCur->info.nSize = 0; + pCur->validNKey = 0; if( pNewPage->nCell<1 ){ return SQLITE_CORRUPT_BKPT; } @@ -3400,6 +3403,7 @@ void sqlite3BtreeMoveToParent(BtCursor *pCur){ releasePage(pPage); pCur->pPage = pParent; pCur->info.nSize = 0; + pCur->validNKey = 0; assert( pParent->idxShift==0 ); pCur->idx = idxParent; } @@ -3438,6 +3442,8 @@ static int moveToRoot(BtCursor *pCur){ } pCur->idx = 0; pCur->info.nSize = 0; + pCur->atLast = 0; + pCur->validNKey = 0; if( pRoot->nCell==0 && !pRoot->leaf ){ Pgno subpage; assert( pRoot->pgno==1 ); @@ -3497,6 +3503,7 @@ static int moveToRightmost(BtCursor *pCur){ if( rc==SQLITE_OK ){ pCur->idx = pPage->nCell - 1; pCur->info.nSize = 0; + pCur->validNKey = 0; } return SQLITE_OK; } @@ -3543,6 +3550,8 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ assert( pCur->eState==CURSOR_VALID ); *pRes = 0; rc = moveToRightmost(pCur); + getCellInfo(pCur); + pCur->atLast = rc==SQLITE_OK; } } return rc; @@ -3589,6 +3598,21 @@ int sqlite3BtreeMoveto( assert( cursorHoldsMutex(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + + /* If the cursor is already positioned at the point we are trying + ** to move to, then just return without doing any work */ + if( pCur->eState==CURSOR_VALID && pCur->validNKey && pCur->pPage->intKey ){ + if( pCur->info.nKey==nKey ){ + *pRes = 0; + return SQLITE_OK; + } + if( pCur->atLast && pCur->info.nKeyinfo.nSize = 0; + pCur->validNKey = 1; if( pPage->intKey ){ u8 *pCell; pCell = findCell(pPage, pCur->idx) + pPage->childPtrSize; @@ -3645,7 +3670,7 @@ int sqlite3BtreeMoveto( u32 dummy; pCell += getVarint32(pCell, &dummy); } - getVarint(pCell, (u64 *)&nCellKey); + getVarint(pCell, (u64*)&nCellKey); if( nCellKeynKey ){ @@ -3672,6 +3697,7 @@ int sqlite3BtreeMoveto( } } if( c==0 ){ + pCur->info.nKey = nCellKey; if( pPage->leafData && !pPage->leaf ){ lwr = pCur->idx; upr = lwr - 1; @@ -3688,6 +3714,7 @@ int sqlite3BtreeMoveto( upr = pCur->idx-1; } if( lwr>upr ){ + pCur->info.nKey = nCellKey; break; } pCur->idx = (lwr+upr)/2; @@ -3709,6 +3736,7 @@ int sqlite3BtreeMoveto( } pCur->idx = lwr; pCur->info.nSize = 0; + pCur->validNKey = 0; rc = moveToChild(pCur, chldPg); if( rc ) goto moveto_finish; } @@ -3778,6 +3806,7 @@ static int btreeNext(BtCursor *pCur, int *pRes){ pCur->idx++; pCur->info.nSize = 0; + pCur->validNKey = 0; if( pCur->idx>=pPage->nCell ){ if( !pPage->leaf ){ rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8])); @@ -3834,6 +3863,7 @@ static int btreePrevious(BtCursor *pCur, int *pRes){ if( rc!=SQLITE_OK ){ return rc; } + pCur->atLast = 0; if( CURSOR_INVALID==pCur->eState ){ *pRes = 1; return SQLITE_OK; @@ -3867,6 +3897,7 @@ static int btreePrevious(BtCursor *pCur, int *pRes){ } pCur->idx--; pCur->info.nSize = 0; + pCur->validNKey = 0; if( pPage->leafData && !pPage->leaf ){ rc = sqlite3BtreePrevious(pCur, pRes); }else{ @@ -5673,6 +5704,7 @@ int sqlite3BtreeInsert( assert( pPage->leaf ); pCur->idx++; pCur->info.nSize = 0; + pCur->validNKey = 0; }else{ assert( pPage->leaf ); } diff --git a/src/btreeInt.h b/src/btreeInt.h index 6045753caf..7932e438c4 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btreeInt.h,v 1.19 2008/03/25 14:24:57 danielk1977 Exp $ +** $Id: btreeInt.h,v 1.20 2008/03/29 16:01:04 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -442,6 +442,8 @@ struct BtCursor { int idx; /* Index of the entry in pPage->aCell[] */ CellInfo info; /* A parse of the cell we are pointing at */ u8 wrFlag; /* True if writable */ + u8 atLast; /* Cursor pointing to the last entry */ + u8 validNKey; /* True if info.nKey is valid */ u8 eState; /* One of the CURSOR_XXX constants (see below) */ void *pKey; /* Saved key that was cursor's last known position */ i64 nKey; /* Size of pKey, or last integer key */