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

Combine the various boolean fields of the BtCursor object into a single

bit-vector.  This allows setting or clearing more than one boolean at a
time and makes the overflow-pgno-cache branch faster than trunk on 
speedtest1.

FossilOrigin-Name: 968fec44d7fde3adbd3e9603e4282351f0d4bda1
This commit is contained in:
drh
2014-03-11 23:40:44 +00:00
parent 5a500afd57
commit 036dbec01c
5 changed files with 69 additions and 67 deletions

View File

@@ -1,5 +1,5 @@
C Enable\sthe\sb-tree\scursor\sobjects\soverflow\spage-number\scache,\swhich\sis\snormally\senabled\sonly\sfor\sincr-blob\scursors,\sfor\sall\scursors. C Combine\sthe\svarious\sboolean\sfields\sof\sthe\sBtCursor\sobject\sinto\sa\ssingle\nbit-vector.\s\sThis\sallows\ssetting\sor\sclearing\smore\sthan\sone\sboolean\sat\sa\ntime\sand\smakes\sthe\soverflow-pgno-cache\sbranch\sfaster\sthan\strunk\son\s\nspeedtest1.
D 2014-03-11T20:33:04.219 D 2014-03-11T23:40:44.961
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -164,9 +164,9 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c c748d8387789d01769e442b9da65e52ed61f408e F src/btree.c 225a3f4d5511d4f5eab38a686f6c7e22290739f3
F src/btree.h 6b0c1a3f0937f9852ec727c820e71dbdd4bd0b27 F src/btree.h 6b0c1a3f0937f9852ec727c820e71dbdd4bd0b27
F src/btreeInt.h 22a8f07968ec821910ab93cc822d7f0c404c74d1 F src/btreeInt.h d1784d1e17d08d29e890190dbb9836fa64573381
F src/build.c 0d50ef95aad63f4c4fc47f3fa2670d4557c45db0 F src/build.c 0d50ef95aad63f4c4fc47f3fa2670d4557c45db0
F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98 F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
@@ -239,7 +239,7 @@ F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8 F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8
F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12 F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
F src/test_backup.c 3875e899222b651e18b662f86e0e50daa946344e F src/test_backup.c 3875e899222b651e18b662f86e0e50daa946344e
F src/test_btree.c 5b89601dcb42a33ba8b820a6b763cc9cb48bac16 F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
F src/test_config.c 0336e0bdbe541b4af89d7e3dd0656e8e6b51e585 F src/test_config.c 0336e0bdbe541b4af89d7e3dd0656e8e6b51e585
F src/test_demovfs.c 69b2085076654ebc18014cbc6386f04409c959a9 F src/test_demovfs.c 69b2085076654ebc18014cbc6386f04409c959a9
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
@@ -1156,10 +1156,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
P 018d317b1257ce68a92908b05c9c7cf1494050d0 P da59198505990a4fe832be7932117c7e014955b7
R 9660042129e37a760044c3b5edf13974 R a9a97bb8415d8a76adacb051af2ccc88
T *branch * overflow-pgno-cache U drh
T *sym-overflow-pgno-cache * Z 90b8a93448c14945f126312bc79eea6f
T -sym-trunk *
U dan
Z 262878375cf61ff20b91f83b47f52bc2

View File

@@ -1 +1 @@
da59198505990a4fe832be7932117c7e014955b7 968fec44d7fde3adbd3e9603e4282351f0d4bda1

View File

@@ -450,7 +450,7 @@ static int cursorHoldsMutex(BtCursor *p){
** Invalidate the overflow cache of the cursor passed as the first argument. ** Invalidate the overflow cache of the cursor passed as the first argument.
** on the shared btree structure pBt. ** on the shared btree structure pBt.
*/ */
#define invalidateOverflowCache(pCur) (pCur->bOvflValid = 0) #define invalidateOverflowCache(pCur) (pCur->curFlags &= ~BTCF_ValidOvfl)
/* /*
** Invalidate the overflow page-list cache for all cursors opened ** Invalidate the overflow page-list cache for all cursors opened
@@ -487,7 +487,7 @@ static void invalidateIncrblobCursors(
BtShared *pBt = pBtree->pBt; BtShared *pBt = pBtree->pBt;
assert( sqlite3BtreeHoldsMutex(pBtree) ); assert( sqlite3BtreeHoldsMutex(pBtree) );
for(p=pBt->pCursor; p; p=p->pNext){ for(p=pBt->pCursor; p; p=p->pNext){
if( p->isIncrblobHandle && (isClearTable || p->info.nKey==iRow) ){ if( (p->curFlags & BTCF_Incrblob)!=0 && (isClearTable || p->info.nKey==iRow) ){
p->eState = CURSOR_INVALID; p->eState = CURSOR_INVALID;
} }
} }
@@ -2543,7 +2543,8 @@ static int countValidCursors(BtShared *pBt, int wrOnly){
BtCursor *pCur; BtCursor *pCur;
int r = 0; int r = 0;
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
if( (wrOnly==0 || pCur->wrFlag) && pCur->eState!=CURSOR_FAULT ) r++; if( (wrOnly==0 || (pCur->curFlags & BTCF_WriteFlag)!=0)
&& pCur->eState!=CURSOR_FAULT ) r++;
} }
return r; return r;
} }
@@ -3618,7 +3619,7 @@ static int btreeCursor(
pCur->pKeyInfo = pKeyInfo; pCur->pKeyInfo = pKeyInfo;
pCur->pBtree = p; pCur->pBtree = p;
pCur->pBt = pBt; pCur->pBt = pBt;
pCur->wrFlag = (u8)wrFlag; pCur->curFlags = wrFlag ? BTCF_WriteFlag : 0;
pCur->pNext = pBt->pCursor; pCur->pNext = pBt->pCursor;
if( pCur->pNext ){ if( pCur->pNext ){
pCur->pNext->pPrev = pCur; pCur->pNext->pPrev = pCur;
@@ -3727,7 +3728,7 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
if( pCur->info.nSize==0 ){ if( pCur->info.nSize==0 ){
int iPage = pCur->iPage; int iPage = pCur->iPage;
btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info);
pCur->validNKey = 1; pCur->curFlags |= BTCF_ValidNKey;
}else{ }else{
assertCellInfo(pCur); assertCellInfo(pCur);
} }
@@ -3737,8 +3738,8 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
#define getCellInfo(pCur) \ #define getCellInfo(pCur) \
if( pCur->info.nSize==0 ){ \ if( pCur->info.nSize==0 ){ \
int iPage = pCur->iPage; \ int iPage = pCur->iPage; \
btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); \ btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); \
pCur->validNKey = 1; \ pCur->curFlags |= BTCF_ValidNKey; \
}else{ \ }else{ \
assertCellInfo(pCur); \ assertCellInfo(pCur); \
} }
@@ -3987,14 +3988,14 @@ static int accessPayload(
nextPage = get4byte(&aPayload[pCur->info.nLocal]); nextPage = get4byte(&aPayload[pCur->info.nLocal]);
/* If the isIncrblobHandle flag is set and the BtCursor.aOverflow[] /* If the BTCF_Incrblob flag is set and the BtCursor.aOverflow[]
** has not been allocated, allocate it now. The array is sized at ** has not been allocated, allocate it now. The array is sized at
** one entry for each overflow page in the overflow chain. The ** one entry for each overflow page in the overflow chain. The
** page number of the first overflow page is stored in aOverflow[0], ** page number of the first overflow page is stored in aOverflow[0],
** etc. A value of 0 in the aOverflow[] array means "not yet known" ** etc. A value of 0 in the aOverflow[] array means "not yet known"
** (the cache is lazily populated). ** (the cache is lazily populated).
*/ */
if( eOp!=2 && !pCur->bOvflValid ){ if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){
int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
if( nOvfl>pCur->nOvflAlloc ){ if( nOvfl>pCur->nOvflAlloc ){
Pgno *aNew = (Pgno*)sqlite3DbRealloc( Pgno *aNew = (Pgno*)sqlite3DbRealloc(
@@ -4009,7 +4010,7 @@ static int accessPayload(
} }
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno)); memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
pCur->bOvflValid = 1; pCur->curFlags |= BTCF_ValidOvfl;
} }
} }
@@ -4017,7 +4018,7 @@ static int accessPayload(
** entry for the first required overflow page is valid, skip ** entry for the first required overflow page is valid, skip
** directly to it. ** directly to it.
*/ */
if( pCur->bOvflValid && pCur->aOverflow[offset/ovflSize] ){ if( (pCur->curFlags & BTCF_ValidOvfl)!=0 && pCur->aOverflow[offset/ovflSize] ){
iIdx = (offset/ovflSize); iIdx = (offset/ovflSize);
nextPage = pCur->aOverflow[iIdx]; nextPage = pCur->aOverflow[iIdx];
offset = (offset%ovflSize); offset = (offset%ovflSize);
@@ -4026,7 +4027,7 @@ static int accessPayload(
for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){ for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){
/* If required, populate the overflow page-list cache. */ /* If required, populate the overflow page-list cache. */
if( pCur->bOvflValid ){ if( (pCur->curFlags & BTCF_ValidOvfl)!=0 ){
assert(!pCur->aOverflow[iIdx] || pCur->aOverflow[iIdx]==nextPage); assert(!pCur->aOverflow[iIdx] || pCur->aOverflow[iIdx]==nextPage);
pCur->aOverflow[iIdx] = nextPage; pCur->aOverflow[iIdx] = nextPage;
} }
@@ -4038,7 +4039,7 @@ static int accessPayload(
** page-list cache, if any, then fall back to the getOverflowPage() ** page-list cache, if any, then fall back to the getOverflowPage()
** function. ** function.
*/ */
if( pCur->bOvflValid && pCur->aOverflow[iIdx+1] ){ if( (pCur->curFlags & BTCF_ValidOvfl)!=0 && pCur->aOverflow[iIdx+1] ){
nextPage = pCur->aOverflow[iIdx+1]; nextPage = pCur->aOverflow[iIdx+1];
} else } else
rc = getOverflowPage(pBt, nextPage, 0, &nextPage); rc = getOverflowPage(pBt, nextPage, 0, &nextPage);
@@ -4239,14 +4240,14 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
return SQLITE_CORRUPT_BKPT; return SQLITE_CORRUPT_BKPT;
} }
rc = getAndInitPage(pBt, newPgno, &pNewPage, rc = getAndInitPage(pBt, newPgno, &pNewPage,
pCur->wrFlag==0 ? PAGER_GET_READONLY : 0); (pCur->curFlags & BTCF_WriteFlag)==0 ? PAGER_GET_READONLY : 0);
if( rc ) return rc; if( rc ) return rc;
pCur->apPage[i+1] = pNewPage; pCur->apPage[i+1] = pNewPage;
pCur->aiIdx[i+1] = 0; pCur->aiIdx[i+1] = 0;
pCur->iPage++; pCur->iPage++;
pCur->info.nSize = 0; pCur->info.nSize = 0;
pCur->validNKey = 0; pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
if( pNewPage->nCell<1 || pNewPage->intKey!=pCur->apPage[i]->intKey ){ if( pNewPage->nCell<1 || pNewPage->intKey!=pCur->apPage[i]->intKey ){
return SQLITE_CORRUPT_BKPT; return SQLITE_CORRUPT_BKPT;
} }
@@ -4304,7 +4305,7 @@ static void moveToParent(BtCursor *pCur){
releasePage(pCur->apPage[pCur->iPage]); releasePage(pCur->apPage[pCur->iPage]);
pCur->iPage--; pCur->iPage--;
pCur->info.nSize = 0; pCur->info.nSize = 0;
pCur->validNKey = 0; pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
} }
/* /*
@@ -4336,7 +4337,7 @@ static int moveToRoot(BtCursor *pCur){
assert( CURSOR_INVALID < CURSOR_REQUIRESEEK ); assert( CURSOR_INVALID < CURSOR_REQUIRESEEK );
assert( CURSOR_VALID < CURSOR_REQUIRESEEK ); assert( CURSOR_VALID < CURSOR_REQUIRESEEK );
assert( CURSOR_FAULT > CURSOR_REQUIRESEEK ); assert( CURSOR_FAULT > CURSOR_REQUIRESEEK );
invalidateOverflowCache(pCur); // invalidateOverflowCache(pCur);
if( pCur->eState>=CURSOR_REQUIRESEEK ){ if( pCur->eState>=CURSOR_REQUIRESEEK ){
if( pCur->eState==CURSOR_FAULT ){ if( pCur->eState==CURSOR_FAULT ){
assert( pCur->skipNext!=SQLITE_OK ); assert( pCur->skipNext!=SQLITE_OK );
@@ -4352,7 +4353,7 @@ static int moveToRoot(BtCursor *pCur){
return SQLITE_OK; return SQLITE_OK;
}else{ }else{
rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0], rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0],
pCur->wrFlag==0 ? PAGER_GET_READONLY : 0); (pCur->curFlags & BTCF_WriteFlag)==0 ? PAGER_GET_READONLY : 0);
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
pCur->eState = CURSOR_INVALID; pCur->eState = CURSOR_INVALID;
return rc; return rc;
@@ -4379,8 +4380,7 @@ static int moveToRoot(BtCursor *pCur){
pCur->aiIdx[0] = 0; pCur->aiIdx[0] = 0;
pCur->info.nSize = 0; pCur->info.nSize = 0;
pCur->atLast = 0; pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);
pCur->validNKey = 0;
if( pRoot->nCell>0 ){ if( pRoot->nCell>0 ){
pCur->eState = CURSOR_VALID; pCur->eState = CURSOR_VALID;
@@ -4443,7 +4443,7 @@ static int moveToRightmost(BtCursor *pCur){
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
pCur->aiIdx[pCur->iPage] = pPage->nCell-1; pCur->aiIdx[pCur->iPage] = pPage->nCell-1;
pCur->info.nSize = 0; pCur->info.nSize = 0;
pCur->validNKey = 0; pCur->curFlags &= ~BTCF_ValidNKey;
} }
return rc; return rc;
} }
@@ -4482,7 +4482,7 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
/* If the cursor already points to the last entry, this is a no-op. */ /* If the cursor already points to the last entry, this is a no-op. */
if( CURSOR_VALID==pCur->eState && pCur->atLast ){ if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG
/* This block serves to assert() that the cursor really does point /* This block serves to assert() that the cursor really does point
** to the last entry in the b-tree. */ ** to the last entry in the b-tree. */
@@ -4505,7 +4505,12 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
assert( pCur->eState==CURSOR_VALID ); assert( pCur->eState==CURSOR_VALID );
*pRes = 0; *pRes = 0;
rc = moveToRightmost(pCur); rc = moveToRightmost(pCur);
pCur->atLast = rc==SQLITE_OK ?1:0; if( rc==SQLITE_OK ){
pCur->curFlags |= BTCF_AtLast;
}else{
pCur->curFlags &= ~BTCF_AtLast;
}
} }
} }
return rc; return rc;
@@ -4556,14 +4561,14 @@ int sqlite3BtreeMovetoUnpacked(
/* If the cursor is already positioned at the point we are trying /* If the cursor is already positioned at the point we are trying
** to move to, then just return without doing any work */ ** to move to, then just return without doing any work */
if( pCur->eState==CURSOR_VALID && pCur->validNKey if( pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0
&& pCur->apPage[0]->intKey && pCur->apPage[0]->intKey
){ ){
if( pCur->info.nKey==intKey ){ if( pCur->info.nKey==intKey ){
*pRes = 0; *pRes = 0;
return SQLITE_OK; return SQLITE_OK;
} }
if( pCur->atLast && pCur->info.nKey<intKey ){ if( (pCur->curFlags & BTCF_AtLast)!=0 && pCur->info.nKey<intKey ){
*pRes = -1; *pRes = -1;
return SQLITE_OK; return SQLITE_OK;
} }
@@ -4629,7 +4634,7 @@ int sqlite3BtreeMovetoUnpacked(
if( lwr>upr ){ c = +1; break; } if( lwr>upr ){ c = +1; break; }
}else{ }else{
assert( nCellKey==intKey ); assert( nCellKey==intKey );
pCur->validNKey = 1; pCur->curFlags |= BTCF_ValidNKey;
pCur->info.nKey = nCellKey; pCur->info.nKey = nCellKey;
pCur->aiIdx[pCur->iPage] = (u16)idx; pCur->aiIdx[pCur->iPage] = (u16)idx;
if( !pPage->leaf ){ if( !pPage->leaf ){
@@ -4731,7 +4736,7 @@ moveto_next_layer:
} }
moveto_finish: moveto_finish:
pCur->info.nSize = 0; pCur->info.nSize = 0;
pCur->validNKey = 0; pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
return rc; return rc;
} }
@@ -4775,8 +4780,8 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
assert( pRes!=0 ); assert( pRes!=0 );
assert( *pRes==0 || *pRes==1 ); assert( *pRes==0 || *pRes==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
invalidateOverflowCache(pCur);
if( pCur->eState!=CURSOR_VALID ){ if( pCur->eState!=CURSOR_VALID ){
invalidateOverflowCache(pCur);
rc = restoreCursorPosition(pCur); rc = restoreCursorPosition(pCur);
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
*pRes = 0; *pRes = 0;
@@ -4810,7 +4815,7 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
testcase( idx>pPage->nCell ); testcase( idx>pPage->nCell );
pCur->info.nSize = 0; pCur->info.nSize = 0;
pCur->validNKey = 0; pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
if( idx>=pPage->nCell ){ if( idx>=pPage->nCell ){
if( !pPage->leaf ){ if( !pPage->leaf ){
rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8])); rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
@@ -4871,8 +4876,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
assert( pRes!=0 ); assert( pRes!=0 );
assert( *pRes==0 || *pRes==1 ); assert( *pRes==0 || *pRes==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
invalidateOverflowCache(pCur); pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl);
pCur->atLast = 0;
if( pCur->eState!=CURSOR_VALID ){ if( pCur->eState!=CURSOR_VALID ){
if( ALWAYS(pCur->eState>=CURSOR_REQUIRESEEK) ){ if( ALWAYS(pCur->eState>=CURSOR_REQUIRESEEK) ){
rc = btreeRestoreCursorPosition(pCur); rc = btreeRestoreCursorPosition(pCur);
@@ -4917,7 +4921,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
moveToParent(pCur); moveToParent(pCur);
} }
pCur->info.nSize = 0; pCur->info.nSize = 0;
pCur->validNKey = 0; pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
pCur->aiIdx[pCur->iPage]--; pCur->aiIdx[pCur->iPage]--;
pPage = pCur->apPage[pCur->iPage]; pPage = pCur->apPage[pCur->iPage];
@@ -6942,7 +6946,7 @@ int sqlite3BtreeInsert(
} }
assert( cursorHoldsMutex(pCur) ); assert( cursorHoldsMutex(pCur) );
assert( pCur->wrFlag && pBt->inTransaction==TRANS_WRITE assert( (pCur->curFlags & BTCF_WriteFlag)!=0 && pBt->inTransaction==TRANS_WRITE
&& (pBt->btsFlags & BTS_READ_ONLY)==0 ); && (pBt->btsFlags & BTS_READ_ONLY)==0 );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
@@ -6975,7 +6979,7 @@ int sqlite3BtreeInsert(
/* If the cursor is currently on the last row and we are appending a /* If the cursor is currently on the last row and we are appending a
** new row onto the end, set the "loc" to avoid an unnecessary btreeMoveto() ** new row onto the end, set the "loc" to avoid an unnecessary btreeMoveto()
** call */ ** call */
if( pCur->validNKey && nKey>0 && pCur->info.nKey==nKey-1 ){ if( (pCur->curFlags&BTCF_ValidNKey)!=0 && nKey>0 && pCur->info.nKey==nKey-1 ){
loc = -1; loc = -1;
} }
} }
@@ -7028,7 +7032,7 @@ int sqlite3BtreeInsert(
/* If no error has occurred and pPage has an overflow cell, call balance() /* If no error has occurred and pPage has an overflow cell, call balance()
** to redistribute the cells within the tree. Since balance() may move ** to redistribute the cells within the tree. Since balance() may move
** the cursor, zero the BtCursor.info.nSize and BtCursor.validNKey ** the cursor, zero the BtCursor.info.nSize and BTCF_ValidNKey
** variables. ** variables.
** **
** Previous versions of SQLite called moveToRoot() to move the cursor ** Previous versions of SQLite called moveToRoot() to move the cursor
@@ -7048,7 +7052,7 @@ int sqlite3BtreeInsert(
*/ */
pCur->info.nSize = 0; pCur->info.nSize = 0;
if( rc==SQLITE_OK && pPage->nOverflow ){ if( rc==SQLITE_OK && pPage->nOverflow ){
pCur->validNKey = 0; pCur->curFlags &= ~(BTCF_ValidNKey);
rc = balance(pCur); rc = balance(pCur);
/* Must make sure nOverflow is reset to zero even if the balance() /* Must make sure nOverflow is reset to zero even if the balance()
@@ -7080,7 +7084,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){
assert( cursorHoldsMutex(pCur) ); assert( cursorHoldsMutex(pCur) );
assert( pBt->inTransaction==TRANS_WRITE ); assert( pBt->inTransaction==TRANS_WRITE );
assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
assert( pCur->wrFlag ); assert( pCur->curFlags & BTCF_WriteFlag );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
assert( !hasReadConflicts(p, pCur->pgnoRoot) ); assert( !hasReadConflicts(p, pCur->pgnoRoot) );
@@ -8384,7 +8388,7 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
int rc; int rc;
assert( cursorHoldsMutex(pCsr) ); assert( cursorHoldsMutex(pCsr) );
assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) ); assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) );
assert( pCsr->isIncrblobHandle ); assert( pCsr->curFlags & BTCF_Incrblob );
rc = restoreCursorPosition(pCsr); rc = restoreCursorPosition(pCsr);
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
@@ -8413,7 +8417,7 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
** (d) there are no conflicting read-locks, and ** (d) there are no conflicting read-locks, and
** (e) the cursor points at a valid row of an intKey table. ** (e) the cursor points at a valid row of an intKey table.
*/ */
if( !pCsr->wrFlag ){ if( (pCsr->curFlags & BTCF_WriteFlag)==0 ){
return SQLITE_READONLY; return SQLITE_READONLY;
} }
assert( (pCsr->pBt->btsFlags & BTS_READ_ONLY)==0 assert( (pCsr->pBt->btsFlags & BTS_READ_ONLY)==0
@@ -8429,7 +8433,7 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
** Mark this cursor as an incremental blob cursor. ** Mark this cursor as an incremental blob cursor.
*/ */
void sqlite3BtreeIncrblobCursor(BtCursor *pCur){ void sqlite3BtreeIncrblobCursor(BtCursor *pCur){
pCur->isIncrblobHandle = 1; pCur->curFlags |= BTCF_Incrblob;
} }
#endif #endif

View File

@@ -496,29 +496,30 @@ struct BtCursor {
BtShared *pBt; /* The BtShared this cursor points to */ BtShared *pBt; /* The BtShared this cursor points to */
BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */
struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */ struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */
#ifndef SQLITE_OMIT_INCRBLOB
int nOvflAlloc; /* Allocated size of aOverflow[] array */
u8 bOvflValid; /* True if size and contents of aOverflow[] valid */
Pgno *aOverflow; /* Cache of overflow page locations */ Pgno *aOverflow; /* Cache of overflow page locations */
#endif
Pgno pgnoRoot; /* The root page of this tree */
CellInfo info; /* A parse of the cell we are pointing at */ CellInfo info; /* A parse of the cell we are pointing at */
i64 nKey; /* Size of pKey, or last integer key */ i64 nKey; /* Size of pKey, or last integer key */
void *pKey; /* Saved key that was cursor's last known position */ void *pKey; /* Saved key that was cursor last known position */
Pgno pgnoRoot; /* The root page of this tree */
int nOvflAlloc; /* Allocated size of aOverflow[] array */
int skipNext; /* Prev() is noop if negative. Next() is noop if positive */ int skipNext; /* Prev() is noop if negative. Next() is noop if positive */
u8 wrFlag; /* True if writable */ u8 curFlags; /* zero or more BTCF_* flags defined below */
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) */ u8 eState; /* One of the CURSOR_XXX constants (see below) */
#ifndef SQLITE_OMIT_INCRBLOB
u8 isIncrblobHandle; /* True if this cursor is an incr. io handle */
#endif
u8 hints; /* As configured by CursorSetHints() */ u8 hints; /* As configured by CursorSetHints() */
i16 iPage; /* Index of current page in apPage */ i16 iPage; /* Index of current page in apPage */
u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */ u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */
MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */ MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */
}; };
/*
** Legal values for BtCursor.curFlags
*/
#define BTCF_ValidNKey 0x01 /* True if info.nKey is valid */
#define BTCF_ValidOvfl 0x02 /* True if aOverflow is valid */
#define BTCF_AtLast 0x04 /* Cursor is pointing ot the last entry */
#define BTCF_WriteFlag 0x08 /* True if a write cursor */
#define BTCF_Incrblob 0x10 /* True if an incremental I/O handle */
/* /*
** Potential values for BtCursor.eState. ** Potential values for BtCursor.eState.
** **

View File

@@ -51,7 +51,7 @@ void sqlite3BtreeCursorList(Btree *p){
BtShared *pBt = p->pBt; BtShared *pBt = p->pBt;
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
MemPage *pPage = pCur->apPage[pCur->iPage]; MemPage *pPage = pCur->apPage[pCur->iPage];
char *zMode = pCur->wrFlag ? "rw" : "ro"; char *zMode = (pCur->curFlags & BTCF_WriteFlag) ? "rw" : "ro";
sqlite3DebugPrintf("CURSOR %p rooted at %4d(%s) currently at %d.%d%s\n", sqlite3DebugPrintf("CURSOR %p rooted at %4d(%s) currently at %d.%d%s\n",
pCur, pCur->pgnoRoot, zMode, pCur, pCur->pgnoRoot, zMode,
pPage ? pPage->pgno : 0, pCur->aiIdx[pCur->iPage], pPage ? pPage->pgno : 0, pCur->aiIdx[pCur->iPage],