From: drh Date: Wed, 15 Apr 2015 19:13:26 +0000 (+0000) Subject: Add the BtCursor.pPage field which is the current page to which the cursor X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fheads%2Fbtree-current-page-cache;p=thirdparty%2Fsqlite.git Add the BtCursor.pPage field which is the current page to which the cursor points, for a very small performance gain. FossilOrigin-Name: a200e1eae9a1350ed2aed9bfe70042fec05dd98b --- diff --git a/manifest b/manifest index 2bcb4fd1f2..70774604bd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Prevent\sthe\sfetchPayload()\sroutine\sfrom\sreporting\sa\scell\ssize\sthat\sextends\noff\sthe\send\sof\sthe\spage\son\sa\spathologically\scorrupted\sdatabase\sfile. -D 2015-04-15T17:26:55.979 +C Add\sthe\sBtCursor.pPage\sfield\swhich\sis\sthe\scurrent\spage\sto\swhich\sthe\scursor\npoints,\sfor\sa\svery\ssmall\sperformance\sgain. +D 2015-04-15T19:13:26.759 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -173,9 +173,9 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 -F src/btree.c c6e32d84442f79d5b96965265d65b3baa231dffc +F src/btree.c 485e357f2409b1d23f21e542190764ea707d567f F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1 -F src/btreeInt.h 973a22a6fd61350b454ad614832b1f0a5e25a1e4 +F src/btreeInt.h 3c791196f75a737b234aee7ba36b37160373fc18 F src/build.c 01b969b20a44a3d9620e597d9af8242348123540 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575 @@ -1250,7 +1250,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 61d72e17916bc043ce53c64e5ba7050a9bae554e -R a75e3890d67000037a79bd4d7c9f248e +P f71053cf658b3260a32ac06f8ba5c2cde0ea54dd +R a88b52422fda2f2ea905aaa2e3a17ff4 +T *branch * btree-current-page-cache +T *sym-btree-current-page-cache * +T -sym-trunk * U drh -Z c0a93418012c7dd834fb5d24bb6e0682 +Z 4cafb2843490ebe751738bc5633d8f3a diff --git a/manifest.uuid b/manifest.uuid index ec95ab78c0..8811cda19b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f71053cf658b3260a32ac06f8ba5c2cde0ea54dd \ No newline at end of file +a200e1eae9a1350ed2aed9bfe70042fec05dd98b \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 51fca4b4be..046c177820 100644 --- a/src/btree.c +++ b/src/btree.c @@ -587,6 +587,7 @@ static void btreeReleaseAllCursorPages(BtCursor *pCur){ pCur->apPage[i] = 0; } pCur->iPage = -1; + pCur->pPage = 0; } @@ -3651,6 +3652,7 @@ int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int writeOnly){ releasePage(p->apPage[i]); p->apPage[i] = 0; } + p->pPage = 0; } sqlite3BtreeLeave(pBtree); } @@ -3865,6 +3867,7 @@ static int btreeCursor( ** variables and link the cursor into the BtShared list. */ pCur->pgnoRoot = (Pgno)iTable; pCur->iPage = -1; + pCur->pPage = 0; pCur->pKeyInfo = pKeyInfo; pCur->pBtree = p; pCur->pBt = pBt; @@ -3966,7 +3969,8 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){ CellInfo info; int iPage = pCur->iPage; memset(&info, 0, sizeof(info)); - btreeParseCell(pCur->apPage[iPage], pCur->aiIdx[iPage], &info); + assert( pCur->pPage==pCur->apPage[iPage] ); + btreeParseCell(pCur->pPage, pCur->aiIdx[iPage], &info); assert( CORRUPT_DB || memcmp(&info, &pCur->info, sizeof(info))==0 ); } #else @@ -3977,7 +3981,8 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){ static void getCellInfo(BtCursor *pCur){ if( pCur->info.nSize==0 ){ int iPage = pCur->iPage; - btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); + assert( pCur->pPage==pCur->apPage[iPage] ); + btreeParseCell(pCur->pPage,pCur->aiIdx[iPage],&pCur->info); pCur->curFlags |= BTCF_ValidNKey; }else{ assertCellInfo(pCur); @@ -3988,7 +3993,8 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){ #define getCellInfo(pCur) \ if( pCur->info.nSize==0 ){ \ int iPage = pCur->iPage; \ - btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); \ + assert( pCur->pPage==pCur->apPage[iPage] ); \ + btreeParseCell(pCur->pPage,pCur->aiIdx[iPage],&pCur->info); \ pCur->curFlags |= BTCF_ValidNKey; \ }else{ \ assertCellInfo(pCur); \ @@ -4043,7 +4049,8 @@ int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ assert( pCur->eState==CURSOR_VALID ); assert( pCur->iPage>=0 ); assert( pCur->iPageapPage[pCur->iPage]->intKeyLeaf==1 ); + assert( pCur->pPage==pCur->apPage[pCur->iPage] ); + assert( pCur->pPage->intKeyLeaf==1 ); getCellInfo(pCur); *pSize = pCur->info.nPayload; return SQLITE_OK; @@ -4197,14 +4204,15 @@ static int accessPayload( unsigned char *aPayload; int rc = SQLITE_OK; int iIdx = 0; - MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */ - BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */ + MemPage *pPage = pCur->pPage; /* Btree page of current entry */ + BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */ #ifdef SQLITE_DIRECT_OVERFLOW_READ unsigned char * const pBufStart = pBuf; int bEnd; /* True if reading to end of data */ #endif assert( pPage ); + assert( pPage==pCur->apPage[pCur->iPage] ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->aiIdx[pCur->iPage]nCell ); assert( cursorHoldsMutex(pCur) ); @@ -4394,8 +4402,10 @@ static int accessPayload( int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); - assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] ); - assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); + assert( pCur->iPage>=0 ); + assert( pCur->apPage[pCur->iPage]==pCur->pPage ); + assert( pCur->pPage!=0 ); + assert( pCur->aiIdx[pCur->iPage]pPage->nCell ); return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0); } @@ -4421,8 +4431,10 @@ int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ rc = restoreCursorPosition(pCur); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_VALID ); - assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] ); - assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); + assert( pCur->iPage>=0 ); + assert( pCur->apPage[pCur->iPage]==pCur->pPage ); + assert( pCur->pPage!=0 ); + assert( pCur->aiIdx[pCur->iPage]pPage->nCell ); rc = accessPayload(pCur, offset, amt, pBuf, 0); } return rc; @@ -4452,15 +4464,18 @@ static const void *fetchPayload( u32 *pAmt /* Write the number of available bytes here */ ){ u32 amt; - assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]); + assert( pCur!=0 ); + assert( pCur->iPage>=0 ); + assert( pCur->apPage[pCur->iPage]==pCur->pPage ); + assert( pCur->pPage!=0 ); assert( pCur->eState==CURSOR_VALID ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); assert( cursorHoldsMutex(pCur) ); - assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); + assert( pCur->aiIdx[pCur->iPage]pPage->nCell ); assert( pCur->info.nSize>0 ); - assert( pCur->info.pPayload>pCur->apPage[pCur->iPage]->aData || CORRUPT_DB ); - assert( pCur->info.pPayloadapPage[pCur->iPage]->aDataEnd ||CORRUPT_DB); - amt = (int)(pCur->apPage[pCur->iPage]->aDataEnd - pCur->info.pPayload); + assert( pCur->info.pPayload>pCur->pPage->aData || CORRUPT_DB ); + assert( pCur->info.pPayloadpPage->aDataEnd || CORRUPT_DB ); + amt = (int)(pCur->pPage->aDataEnd - pCur->info.pPayload); if( pCur->info.nLocalinfo.nLocal; *pAmt = amt; return (void*)pCur->info.pPayload; @@ -4514,7 +4529,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){ rc = getAndInitPage(pBt, newPgno, &pNewPage, (pCur->curFlags & BTCF_WriteFlag)==0 ? PAGER_GET_READONLY : 0); if( rc ) return rc; - pCur->apPage[i+1] = pNewPage; + pCur->apPage[i+1] = pCur->pPage = pNewPage; pCur->aiIdx[i+1] = 0; pCur->iPage++; @@ -4560,16 +4575,18 @@ static void moveToParent(BtCursor *pCur){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->iPage>0 ); - assert( pCur->apPage[pCur->iPage] ); + assert( pCur->pPage==pCur->apPage[pCur->iPage] ); + assert( pCur->pPage!=0 ); assertParentIndex( pCur->apPage[pCur->iPage-1], pCur->aiIdx[pCur->iPage-1], - pCur->apPage[pCur->iPage]->pgno + pCur->pPage->pgno ); testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell ); - releasePage(pCur->apPage[pCur->iPage]); + releasePage(pCur->pPage); pCur->iPage--; + pCur->pPage = pCur->apPage[pCur->iPage]; pCur->info.nSize = 0; pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); } @@ -4625,7 +4642,8 @@ static int moveToRoot(BtCursor *pCur){ } pCur->iPage = 0; } - pRoot = pCur->apPage[0]; + assert( pCur->iPage==0 ); + pRoot = pCur->pPage = pCur->apPage[0]; assert( pRoot->pgno==pCur->pgnoRoot ); /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor @@ -4675,7 +4693,7 @@ static int moveToLeftmost(BtCursor *pCur){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); - while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){ + while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){ assert( pCur->aiIdx[pCur->iPage]nCell ); pgno = get4byte(findCell(pPage, pCur->aiIdx[pCur->iPage])); rc = moveToChild(pCur, pgno); @@ -4700,7 +4718,7 @@ static int moveToRightmost(BtCursor *pCur){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); - while( !(pPage = pCur->apPage[pCur->iPage])->leaf ){ + while( !(pPage = pCur->pPage)->leaf ){ pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); pCur->aiIdx[pCur->iPage] = pPage->nCell; rc = moveToChild(pCur, pgno); @@ -4723,11 +4741,12 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); rc = moveToRoot(pCur); if( rc==SQLITE_OK ){ + assert( pCur->pPage==pCur->apPage[pCur->iPage] ); if( pCur->eState==CURSOR_INVALID ){ - assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 ); + assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); *pRes = 1; }else{ - assert( pCur->apPage[pCur->iPage]->nCell>0 ); + assert( pCur->pPage->nCell>0 ); *pRes = 0; rc = moveToLeftmost(pCur); } @@ -4754,8 +4773,9 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ for(ii=0; iiiPage; ii++){ assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell ); } - assert( pCur->aiIdx[pCur->iPage]==pCur->apPage[pCur->iPage]->nCell-1 ); - assert( pCur->apPage[pCur->iPage]->leaf ); + assert( pCur->pPage==pCur->apPage[pCur->iPage] ); + assert( pCur->aiIdx[pCur->iPage]==pCur->pPage->nCell-1 ); + assert( pCur->pPage->leaf ); #endif return SQLITE_OK; } @@ -4853,19 +4873,20 @@ int sqlite3BtreeMovetoUnpacked( if( rc ){ return rc; } - assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage] ); - assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->isInit ); - assert( pCur->eState==CURSOR_INVALID || pCur->apPage[pCur->iPage]->nCell>0 ); + assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]==pCur->pPage ); + assert( pCur->pgnoRoot==0 || pCur->pPage!=0 ); + assert( pCur->pgnoRoot==0 || pCur->pPage->isInit ); + assert( pCur->eState==CURSOR_INVALID || pCur->pPage->nCell>0 ); if( pCur->eState==CURSOR_INVALID ){ *pRes = -1; - assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 ); + assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); return SQLITE_OK; } - assert( pCur->apPage[0]->intKey || pIdxKey ); + assert( pCur->pPage->intKey || pIdxKey ); for(;;){ int lwr, upr, idx, c; Pgno chldPg; - MemPage *pPage = pCur->apPage[pCur->iPage]; + MemPage *pPage = pCur->pPage; u8 *pCell; /* Pointer to current cell in pPage */ /* pPage->nCell must be greater than zero. If this is the root-page @@ -4988,7 +5009,7 @@ int sqlite3BtreeMovetoUnpacked( assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) ); assert( pPage->isInit ); if( pPage->leaf ){ - assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); + assert( pCur->aiIdx[pCur->iPage]pPage->nCell ); pCur->aiIdx[pCur->iPage] = (u16)idx; *pRes = c; rc = SQLITE_OK; @@ -5076,7 +5097,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){ } } - pPage = pCur->apPage[pCur->iPage]; + pPage = pCur->pPage; idx = ++pCur->aiIdx[pCur->iPage]; assert( pPage->isInit ); @@ -5100,7 +5121,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){ return SQLITE_OK; } moveToParent(pCur); - pPage = pCur->apPage[pCur->iPage]; + pPage = pCur->pPage; }while( pCur->aiIdx[pCur->iPage]>=pPage->nCell ); if( pPage->intKey ){ return sqlite3BtreeNext(pCur, pRes); @@ -5124,7 +5145,7 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); *pRes = 0; if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur, pRes); - pPage = pCur->apPage[pCur->iPage]; + pPage = pCur->pPage; if( (++pCur->aiIdx[pCur->iPage])>=pPage->nCell ){ pCur->aiIdx[pCur->iPage]--; return btreeNext(pCur, pRes); @@ -5187,7 +5208,8 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){ } } - pPage = pCur->apPage[pCur->iPage]; + pPage = pCur->pPage; + assert( pPage==pCur->apPage[pCur->iPage] ); assert( pPage->isInit ); if( !pPage->leaf ){ int idx = pCur->aiIdx[pCur->iPage]; @@ -5207,7 +5229,8 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){ assert( (pCur->curFlags & (BTCF_ValidNKey|BTCF_ValidOvfl))==0 ); pCur->aiIdx[pCur->iPage]--; - pPage = pCur->apPage[pCur->iPage]; + assert( pCur->apPage[pCur->iPage]==pCur->pPage ); + pPage = pCur->pPage; if( pPage->intKey && !pPage->leaf ){ rc = sqlite3BtreePrevious(pCur, pRes); }else{ @@ -5226,7 +5249,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ pCur->info.nSize = 0; if( pCur->eState!=CURSOR_VALID || pCur->aiIdx[pCur->iPage]==0 - || pCur->apPage[pCur->iPage]->leaf==0 + || pCur->pPage->leaf==0 ){ return btreePrevious(pCur, pRes); } @@ -7419,7 +7442,8 @@ static int balance(BtCursor *pCur){ do { int iPage = pCur->iPage; - MemPage *pPage = pCur->apPage[iPage]; + MemPage *pPage = pCur->pPage; + assert( pPage==pCur->apPage[iPage] ); if( iPage==0 ){ if( pPage->nOverflow ){ @@ -7434,7 +7458,8 @@ static int balance(BtCursor *pCur){ pCur->iPage = 1; pCur->aiIdx[0] = 0; pCur->aiIdx[1] = 0; - assert( pCur->apPage[1]->nOverflow ); + pCur->pPage = pCur->apPage[1]; + assert( pCur->pPage->nOverflow ); } }else{ break; @@ -7513,6 +7538,7 @@ static int balance(BtCursor *pCur){ releasePage(pPage); pCur->iPage--; assert( pCur->iPage>=0 ); + pCur->pPage = pCur->apPage[pCur->iPage]; } }while( rc==SQLITE_OK ); @@ -7615,7 +7641,8 @@ int sqlite3BtreeInsert( } assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) ); - pPage = pCur->apPage[pCur->iPage]; + assert( pCur->pPage==pCur->apPage[pCur->iPage] ); + pPage = pCur->pPage; assert( pPage->intKey || nKey>=0 ); assert( pPage->leaf || !pPage->intKey ); @@ -7682,10 +7709,11 @@ int sqlite3BtreeInsert( ** fails. Internal data structure corruption will result otherwise. ** Also, set the cursor state to invalid. This stops saveCursorPosition() ** from trying to save the current position of the cursor. */ - pCur->apPage[pCur->iPage]->nOverflow = 0; + assert( pCur->pPage==pCur->apPage[pCur->iPage] ); + pCur->pPage->nOverflow = 0; pCur->eState = CURSOR_INVALID; } - assert( pCur->apPage[pCur->iPage]->nOverflow==0 ); + assert( pCur->pPage->nOverflow==0 ); end_insert: return rc; @@ -7711,8 +7739,9 @@ int sqlite3BtreeDelete(BtCursor *pCur){ assert( pCur->curFlags & BTCF_WriteFlag ); assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); assert( !hasReadConflicts(p, pCur->pgnoRoot) ); + assert( pCur->pPage==pCur->apPage[pCur->iPage] ); - if( NEVER(pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell) + if( NEVER(pCur->aiIdx[pCur->iPage]>=pCur->pPage->nCell) || NEVER(pCur->eState!=CURSOR_VALID) ){ return SQLITE_ERROR; /* Something has gone awry. */ @@ -7762,7 +7791,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){ ** node. The cell from the leaf node needs to be moved to the internal ** node to replace the deleted cell. */ if( !pPage->leaf ){ - MemPage *pLeaf = pCur->apPage[pCur->iPage]; + MemPage *pLeaf = pCur->pPage; int nCell; Pgno n = pCur->apPage[iCellDepth+1]->pgno; unsigned char *pTmp; @@ -7798,6 +7827,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){ while( pCur->iPage>iCellDepth ){ releasePage(pCur->apPage[pCur->iPage--]); } + pCur->pPage = pCur->apPage[pCur->iPage]; rc = balance(pCur); } @@ -8302,7 +8332,8 @@ int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){ ** this page contains countable entries. Increment the entry counter ** accordingly. */ - pPage = pCur->apPage[pCur->iPage]; + assert( pCur->pPage==pCur->apPage[pCur->iPage] ); + pPage = pCur->pPage; if( pPage->leaf || !pPage->intKey ){ nEntry += pPage->nCell; } @@ -8325,10 +8356,11 @@ int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){ return moveToRoot(pCur); } moveToParent(pCur); - }while ( pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell ); + }while ( pCur->aiIdx[pCur->iPage]>=pCur->pPage->nCell ); pCur->aiIdx[pCur->iPage]++; - pPage = pCur->apPage[pCur->iPage]; + assert( pCur->pPage==pCur->apPage[pCur->iPage] ); + pPage = pCur->pPage; } /* Descend to the child node of the cell that the cursor currently @@ -9111,6 +9143,7 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ assert( hasSharedCacheTableLock(pCsr->pBtree, pCsr->pgnoRoot, 0, 2) ); assert( !hasReadConflicts(pCsr->pBtree, pCsr->pgnoRoot) ); assert( pCsr->apPage[pCsr->iPage]->intKey ); + assert( pCsr->pPage==pCsr->apPage[pCsr->iPage] ); return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1); } diff --git a/src/btreeInt.h b/src/btreeInt.h index 33ef641059..d457832e75 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -518,6 +518,7 @@ struct BtCursor { u8 hints; /* As configured by CursorSetHints() */ i16 iPage; /* Index of current page in apPage */ u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */ + MemPage *pPage; /* Current page */ MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */ };