Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 37f686bd33 |
@@ -1,5 +1,5 @@
|
||||
C Avoid\sa\sfew\sunnecessary\scalls\sto\ssqlite3BtreeMovetoUnpacked().
|
||||
D 2016-11-10T20:42:08.396
|
||||
C Break\sup\sthe\ssqlite3BtreeMovetoUnpacked()\sroutine\sinto\san\seponymous\sroutine\nand\ssqlite3BtreeMovetoIntkey().\s\sEach\sroutine\sspecializes\sin\sa\ssingle\skind\sof\nbtree.
|
||||
D 2016-11-10T21:19:35.219
|
||||
F Makefile.in 6fd48ffcf7c2deea7499062d1f3747f986c19678
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc e0217f2d35a0448abbe4b066132ae20136e8b408
|
||||
@@ -330,8 +330,8 @@ F src/auth.c 930b376a9c56998557367e6f7f8aaeac82a2a792
|
||||
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
|
||||
F src/bitvec.c 3ee4c8b2c94ed3a7377256e18199e6ff5cf33f63
|
||||
F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73
|
||||
F src/btree.c 592a72c259752b3cae6928e3f2448a2cb540b032
|
||||
F src/btree.h 630303068c82a359f6ddf202b205ae927721b090
|
||||
F src/btree.c 0974c9d93786648343ba7a271c070d8f9a7ba4cd
|
||||
F src/btree.h f62e4c550e704acb12dc9c4089e05dcd2bc1808b
|
||||
F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5
|
||||
F src/build.c 178f16698cbcb43402c343a9413fe22c99ffee21
|
||||
F src/callback.c 2e76147783386374bf01b227f752c81ec872d730
|
||||
@@ -454,11 +454,11 @@ F src/update.c bb9854778bdbbbca55d7533e55058733bd3fefe3
|
||||
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
|
||||
F src/util.c 3e2da6101888d073e79ecc6af5e0a2f70fa1e498
|
||||
F src/vacuum.c 33c174b28886b2faf26e503b5a49a1c01a9b1c16
|
||||
F src/vdbe.c f1a8e5bf7747f2e731812804cb65d4d07d86862e
|
||||
F src/vdbe.c d9e17f9804d6ce20ec2d5b844fc9461713e60596
|
||||
F src/vdbe.h c044be7050ac6bf596eecc6ab159f5dbc020a3b7
|
||||
F src/vdbeInt.h 29b25318a0286c4b2599c0fbef6acf524398489a
|
||||
F src/vdbeapi.c 97129bec6b1553da50d8e73f523c278bda66d9f6
|
||||
F src/vdbeaux.c 52d9b840859f260ce8418be9333dd77c902e1c74
|
||||
F src/vdbeaux.c ba211189d07b4ecb3209c5b236512e786b499786
|
||||
F src/vdbeblob.c 3e82a797b60c3b9fed7b8de8c539ca7607874937
|
||||
F src/vdbemem.c fcdd73a2001a673f48a244a77b1038928ae729c9
|
||||
F src/vdbesort.c 91fda3909326860382b0ca8aa251e609c6a9d62c
|
||||
@@ -1530,7 +1530,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P f7041cbb63b912f9ecad538804b6f2383efbec4e
|
||||
R d3d5f8b510b4445e2e54b3c5a8a5e3a5
|
||||
P eac0e827a61cfec4dd9b6d407ff398e9fda3510b
|
||||
R ba7bc1acb04a8d9f868e5f35605c70ca
|
||||
T *branch * split-moveto
|
||||
T *sym-split-moveto *
|
||||
T -sym-unpacked-IdxInsert *
|
||||
U drh
|
||||
Z 4683912e0f389e0006dbaa0668a519e9
|
||||
Z 427f2c7c546b65337746f9a6ce50edb5
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
eac0e827a61cfec4dd9b6d407ff398e9fda3510b
|
||||
9a64a4f2353576ba742c2ddbf4264d00704066a1
|
||||
+208
-152
@@ -777,12 +777,10 @@ static int btreeMoveto(
|
||||
sqlite3DbFree(pCur->pKeyInfo->db, pFree);
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, bias, pRes);
|
||||
if( pFree ) sqlite3DbFree(pCur->pKeyInfo->db, pFree);
|
||||
}else{
|
||||
pIdxKey = 0;
|
||||
}
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
|
||||
if( pFree ){
|
||||
sqlite3DbFree(pCur->pKeyInfo->db, pFree);
|
||||
rc = sqlite3BtreeMovetoIntkey(pCur, nKey, bias, pRes);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -5075,7 +5073,6 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
|
||||
int sqlite3BtreeMovetoUnpacked(
|
||||
BtCursor *pCur, /* The cursor to be moved */
|
||||
UnpackedRecord *pIdxKey, /* Unpacked index key */
|
||||
i64 intKey, /* The table key */
|
||||
int biasRight, /* If true, bias the search to the high end */
|
||||
int *pRes /* Write search results here */
|
||||
){
|
||||
@@ -5085,35 +5082,15 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
assert( cursorOwnsBtShared(pCur) );
|
||||
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
|
||||
assert( pRes );
|
||||
assert( (pIdxKey==0)==(pCur->pKeyInfo==0) );
|
||||
assert( pCur->eState!=CURSOR_VALID || (pIdxKey==0)==(pCur->curIntKey!=0) );
|
||||
|
||||
/* If the cursor is already positioned at the point we are trying
|
||||
** to move to, then just return without doing any work */
|
||||
if( pIdxKey==0
|
||||
&& pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0
|
||||
){
|
||||
if( pCur->info.nKey==intKey ){
|
||||
*pRes = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
if( (pCur->curFlags & BTCF_AtLast)!=0 && pCur->info.nKey<intKey ){
|
||||
*pRes = -1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if( pIdxKey ){
|
||||
xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
|
||||
pIdxKey->errCode = 0;
|
||||
assert( pIdxKey->default_rc==1
|
||||
|| pIdxKey->default_rc==0
|
||||
|| pIdxKey->default_rc==-1
|
||||
);
|
||||
}else{
|
||||
xRecordCompare = 0; /* All keys are integers */
|
||||
}
|
||||
assert( pIdxKey );
|
||||
assert( pCur->curIntKey==0 || pCur->eState!=CURSOR_VALID );
|
||||
|
||||
xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
|
||||
pIdxKey->errCode = 0;
|
||||
assert( pIdxKey->default_rc==1
|
||||
|| pIdxKey->default_rc==0
|
||||
|| pIdxKey->default_rc==-1
|
||||
);
|
||||
rc = moveToRoot(pCur);
|
||||
if( rc ){
|
||||
return rc;
|
||||
@@ -5126,8 +5103,8 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
|
||||
return SQLITE_OK;
|
||||
}
|
||||
assert( pCur->apPage[0]->intKey==pCur->curIntKey );
|
||||
assert( pCur->curIntKey || pIdxKey );
|
||||
assert( !pCur->apPage[0]->intKey );
|
||||
assert( !pCur->curIntKey );
|
||||
for(;;){
|
||||
int lwr, upr, idx, c;
|
||||
Pgno chldPg;
|
||||
@@ -5147,124 +5124,89 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
assert( biasRight==0 || biasRight==1 );
|
||||
idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
|
||||
pCur->aiIdx[pCur->iPage] = (u16)idx;
|
||||
if( xRecordCompare==0 ){
|
||||
for(;;){
|
||||
i64 nCellKey;
|
||||
pCell = findCellPastPtr(pPage, idx);
|
||||
if( pPage->intKeyLeaf ){
|
||||
while( 0x80 <= *(pCell++) ){
|
||||
if( pCell>=pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
}
|
||||
getVarint(pCell, (u64*)&nCellKey);
|
||||
if( nCellKey<intKey ){
|
||||
lwr = idx+1;
|
||||
if( lwr>upr ){ c = -1; break; }
|
||||
}else if( nCellKey>intKey ){
|
||||
upr = idx-1;
|
||||
if( lwr>upr ){ c = +1; break; }
|
||||
}else{
|
||||
assert( nCellKey==intKey );
|
||||
pCur->curFlags |= BTCF_ValidNKey;
|
||||
pCur->info.nKey = nCellKey;
|
||||
pCur->aiIdx[pCur->iPage] = (u16)idx;
|
||||
if( !pPage->leaf ){
|
||||
lwr = idx;
|
||||
goto moveto_next_layer;
|
||||
}else{
|
||||
*pRes = 0;
|
||||
rc = SQLITE_OK;
|
||||
goto moveto_finish;
|
||||
}
|
||||
}
|
||||
assert( lwr+upr>=0 );
|
||||
idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2; */
|
||||
}
|
||||
}else{
|
||||
for(;;){
|
||||
int nCell; /* Size of the pCell cell in bytes */
|
||||
pCell = findCellPastPtr(pPage, idx);
|
||||
for(;;){
|
||||
int nCell; /* Size of the pCell cell in bytes */
|
||||
pCell = findCellPastPtr(pPage, idx);
|
||||
|
||||
/* The maximum supported page-size is 65536 bytes. This means that
|
||||
** the maximum number of record bytes stored on an index B-Tree
|
||||
** page is less than 16384 bytes and may be stored as a 2-byte
|
||||
** varint. This information is used to attempt to avoid parsing
|
||||
** the entire cell by checking for the cases where the record is
|
||||
** stored entirely within the b-tree page by inspecting the first
|
||||
** 2 bytes of the cell.
|
||||
*/
|
||||
nCell = pCell[0];
|
||||
if( nCell<=pPage->max1bytePayload ){
|
||||
/* This branch runs if the record-size field of the cell is a
|
||||
** single byte varint and the record fits entirely on the main
|
||||
** b-tree page. */
|
||||
testcase( pCell+nCell+1==pPage->aDataEnd );
|
||||
c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
|
||||
}else if( !(pCell[1] & 0x80)
|
||||
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
|
||||
){
|
||||
/* The record-size field is a 2 byte varint and the record
|
||||
** fits entirely on the main b-tree page. */
|
||||
testcase( pCell+nCell+2==pPage->aDataEnd );
|
||||
c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
|
||||
}else{
|
||||
/* The record flows over onto one or more overflow pages. In
|
||||
** this case the whole cell needs to be parsed, a buffer allocated
|
||||
** and accessPayload() used to retrieve the record into the
|
||||
** buffer before VdbeRecordCompare() can be called.
|
||||
**
|
||||
** If the record is corrupt, the xRecordCompare routine may read
|
||||
** up to two varints past the end of the buffer. An extra 18
|
||||
** bytes of padding is allocated at the end of the buffer in
|
||||
** case this happens. */
|
||||
void *pCellKey;
|
||||
u8 * const pCellBody = pCell - pPage->childPtrSize;
|
||||
pPage->xParseCell(pPage, pCellBody, &pCur->info);
|
||||
nCell = (int)pCur->info.nKey;
|
||||
testcase( nCell<0 ); /* True if key size is 2^32 or more */
|
||||
testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */
|
||||
testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */
|
||||
testcase( nCell==2 ); /* Minimum legal index key size */
|
||||
if( nCell<2 ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto moveto_finish;
|
||||
}
|
||||
pCellKey = sqlite3Malloc( nCell+18 );
|
||||
if( pCellKey==0 ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
goto moveto_finish;
|
||||
}
|
||||
pCur->aiIdx[pCur->iPage] = (u16)idx;
|
||||
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 2);
|
||||
if( rc ){
|
||||
sqlite3_free(pCellKey);
|
||||
goto moveto_finish;
|
||||
}
|
||||
c = xRecordCompare(nCell, pCellKey, pIdxKey);
|
||||
sqlite3_free(pCellKey);
|
||||
}
|
||||
assert(
|
||||
(pIdxKey->errCode!=SQLITE_CORRUPT || c==0)
|
||||
&& (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed)
|
||||
);
|
||||
if( c<0 ){
|
||||
lwr = idx+1;
|
||||
}else if( c>0 ){
|
||||
upr = idx-1;
|
||||
}else{
|
||||
assert( c==0 );
|
||||
*pRes = 0;
|
||||
rc = SQLITE_OK;
|
||||
pCur->aiIdx[pCur->iPage] = (u16)idx;
|
||||
if( pIdxKey->errCode ) rc = SQLITE_CORRUPT;
|
||||
/* The maximum supported page-size is 65536 bytes. This means that
|
||||
** the maximum number of record bytes stored on an index B-Tree
|
||||
** page is less than 16384 bytes and may be stored as a 2-byte
|
||||
** varint. This information is used to attempt to avoid parsing
|
||||
** the entire cell by checking for the cases where the record is
|
||||
** stored entirely within the b-tree page by inspecting the first
|
||||
** 2 bytes of the cell.
|
||||
*/
|
||||
nCell = pCell[0];
|
||||
if( nCell<=pPage->max1bytePayload ){
|
||||
/* This branch runs if the record-size field of the cell is a
|
||||
** single byte varint and the record fits entirely on the main
|
||||
** b-tree page. */
|
||||
testcase( pCell+nCell+1==pPage->aDataEnd );
|
||||
c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
|
||||
}else if( !(pCell[1] & 0x80)
|
||||
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
|
||||
){
|
||||
/* The record-size field is a 2 byte varint and the record
|
||||
** fits entirely on the main b-tree page. */
|
||||
testcase( pCell+nCell+2==pPage->aDataEnd );
|
||||
c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
|
||||
}else{
|
||||
/* The record flows over onto one or more overflow pages. In
|
||||
** this case the whole cell needs to be parsed, a buffer allocated
|
||||
** and accessPayload() used to retrieve the record into the
|
||||
** buffer before VdbeRecordCompare() can be called.
|
||||
**
|
||||
** If the record is corrupt, the xRecordCompare routine may read
|
||||
** up to two varints past the end of the buffer. An extra 18
|
||||
** bytes of padding is allocated at the end of the buffer in
|
||||
** case this happens. */
|
||||
void *pCellKey;
|
||||
u8 * const pCellBody = pCell - pPage->childPtrSize;
|
||||
pPage->xParseCell(pPage, pCellBody, &pCur->info);
|
||||
nCell = (int)pCur->info.nKey;
|
||||
testcase( nCell<0 ); /* True if key size is 2^32 or more */
|
||||
testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */
|
||||
testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */
|
||||
testcase( nCell==2 ); /* Minimum legal index key size */
|
||||
if( nCell<2 ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto moveto_finish;
|
||||
}
|
||||
if( lwr>upr ) break;
|
||||
assert( lwr+upr>=0 );
|
||||
idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */
|
||||
pCellKey = sqlite3Malloc( nCell+18 );
|
||||
if( pCellKey==0 ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
goto moveto_finish;
|
||||
}
|
||||
pCur->aiIdx[pCur->iPage] = (u16)idx;
|
||||
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 2);
|
||||
if( rc ){
|
||||
sqlite3_free(pCellKey);
|
||||
goto moveto_finish;
|
||||
}
|
||||
c = xRecordCompare(nCell, pCellKey, pIdxKey);
|
||||
sqlite3_free(pCellKey);
|
||||
}
|
||||
assert(
|
||||
(pIdxKey->errCode!=SQLITE_CORRUPT || c==0)
|
||||
&& (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed)
|
||||
);
|
||||
if( c<0 ){
|
||||
lwr = idx+1;
|
||||
}else if( c>0 ){
|
||||
upr = idx-1;
|
||||
}else{
|
||||
assert( c==0 );
|
||||
*pRes = 0;
|
||||
rc = SQLITE_OK;
|
||||
pCur->aiIdx[pCur->iPage] = (u16)idx;
|
||||
if( pIdxKey->errCode ) rc = SQLITE_CORRUPT;
|
||||
goto moveto_finish;
|
||||
}
|
||||
if( lwr>upr ) break;
|
||||
assert( lwr+upr>=0 );
|
||||
idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */
|
||||
}
|
||||
assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
|
||||
assert( lwr==upr+1 );
|
||||
assert( pPage->isInit );
|
||||
if( pPage->leaf ){
|
||||
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
|
||||
@@ -5273,7 +5215,6 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
rc = SQLITE_OK;
|
||||
goto moveto_finish;
|
||||
}
|
||||
moveto_next_layer:
|
||||
if( lwr>=pPage->nCell ){
|
||||
chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
|
||||
}else{
|
||||
@@ -5288,6 +5229,121 @@ moveto_finish:
|
||||
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
|
||||
return rc;
|
||||
}
|
||||
int sqlite3BtreeMovetoIntkey(
|
||||
BtCursor *pCur, /* The cursor to be moved */
|
||||
i64 intKey, /* The table key */
|
||||
int biasRight, /* If true, bias the search to the high end */
|
||||
int *pRes /* Write search results here */
|
||||
){
|
||||
int rc;
|
||||
|
||||
assert( cursorOwnsBtShared(pCur) );
|
||||
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
|
||||
assert( pRes );
|
||||
assert( pCur->pKeyInfo==0 );
|
||||
assert( pCur->curIntKey || pCur->eState!=CURSOR_VALID );
|
||||
|
||||
/* 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->curFlags & BTCF_ValidNKey)!=0 ){
|
||||
if( pCur->info.nKey==intKey ){
|
||||
*pRes = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
if( (pCur->curFlags & BTCF_AtLast)!=0 && pCur->info.nKey<intKey ){
|
||||
*pRes = -1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
rc = moveToRoot(pCur);
|
||||
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 );
|
||||
if( pCur->eState==CURSOR_INVALID ){
|
||||
*pRes = -1;
|
||||
assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
|
||||
return SQLITE_OK;
|
||||
}
|
||||
assert( pCur->apPage[0]->intKey );
|
||||
assert( pCur->curIntKey );
|
||||
for(;;){
|
||||
int lwr, upr, idx, c;
|
||||
Pgno chldPg;
|
||||
MemPage *pPage = pCur->apPage[pCur->iPage];
|
||||
u8 *pCell; /* Pointer to current cell in pPage */
|
||||
|
||||
/* pPage->nCell must be greater than zero. If this is the root-page
|
||||
** the cursor would have been INVALID above and this for(;;) loop
|
||||
** not run. If this is not the root-page, then the moveToChild() routine
|
||||
** would have already detected db corruption. Similarly, pPage must
|
||||
** be the right kind (index or table) of b-tree page. Otherwise
|
||||
** a moveToChild() or moveToRoot() call would have detected corruption. */
|
||||
assert( pPage->nCell>0 );
|
||||
assert( pPage->intKey );
|
||||
lwr = 0;
|
||||
upr = pPage->nCell-1;
|
||||
assert( biasRight==0 || biasRight==1 );
|
||||
idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
|
||||
pCur->aiIdx[pCur->iPage] = (u16)idx;
|
||||
for(;;){
|
||||
i64 nCellKey;
|
||||
pCell = findCellPastPtr(pPage, idx);
|
||||
if( pPage->intKeyLeaf ){
|
||||
while( 0x80 <= *(pCell++) ){
|
||||
if( pCell>=pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
}
|
||||
getVarint(pCell, (u64*)&nCellKey);
|
||||
if( nCellKey<intKey ){
|
||||
lwr = idx+1;
|
||||
if( lwr>upr ){ c = -1; break; }
|
||||
}else if( nCellKey>intKey ){
|
||||
upr = idx-1;
|
||||
if( lwr>upr ){ c = +1; break; }
|
||||
}else{
|
||||
assert( nCellKey==intKey );
|
||||
pCur->curFlags |= BTCF_ValidNKey;
|
||||
pCur->info.nKey = nCellKey;
|
||||
pCur->aiIdx[pCur->iPage] = (u16)idx;
|
||||
if( !pPage->leaf ){
|
||||
lwr = idx;
|
||||
goto intkey_moveto_next_layer;
|
||||
}else{
|
||||
*pRes = 0;
|
||||
rc = SQLITE_OK;
|
||||
goto intkey_moveto_finish;
|
||||
}
|
||||
}
|
||||
assert( lwr+upr>=0 );
|
||||
idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2; */
|
||||
}
|
||||
assert( lwr==upr+1 || !pPage->leaf );
|
||||
assert( pPage->isInit );
|
||||
if( pPage->leaf ){
|
||||
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
|
||||
pCur->aiIdx[pCur->iPage] = (u16)idx;
|
||||
*pRes = c;
|
||||
rc = SQLITE_OK;
|
||||
goto intkey_moveto_finish;
|
||||
}
|
||||
intkey_moveto_next_layer:
|
||||
if( lwr>=pPage->nCell ){
|
||||
chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
|
||||
}else{
|
||||
chldPg = get4byte(findCell(pPage, lwr));
|
||||
}
|
||||
pCur->aiIdx[pCur->iPage] = (u16)lwr;
|
||||
rc = moveToChild(pCur, chldPg);
|
||||
if( rc ) break;
|
||||
}
|
||||
intkey_moveto_finish:
|
||||
pCur->info.nSize = 0;
|
||||
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -8019,7 +8075,7 @@ int sqlite3BtreeInsert(
|
||||
&& pCur->info.nKey==pX->nKey-1 ){
|
||||
loc = -1;
|
||||
}else if( loc==0 ){
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, appendBias, &loc);
|
||||
rc = sqlite3BtreeMovetoIntkey(pCur, pX->nKey, appendBias, &loc);
|
||||
if( rc ) return rc;
|
||||
}
|
||||
}else if( loc==0 ){
|
||||
@@ -8029,7 +8085,7 @@ int sqlite3BtreeInsert(
|
||||
r.pKeyInfo = pCur->pKeyInfo;
|
||||
r.aMem = pX->aMem;
|
||||
r.nField = pX->nMem;
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, appendBias, &loc);
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCur, &r, appendBias, &loc);
|
||||
}else{
|
||||
rc = btreeMoveto(pCur, pX->pKey, pX->nKey, appendBias, &loc);
|
||||
}
|
||||
|
||||
@@ -241,6 +241,11 @@ int sqlite3BtreeCloseCursor(BtCursor*);
|
||||
int sqlite3BtreeMovetoUnpacked(
|
||||
BtCursor*,
|
||||
UnpackedRecord *pUnKey,
|
||||
int bias,
|
||||
int *pRes
|
||||
);
|
||||
int sqlite3BtreeMovetoIntkey(
|
||||
BtCursor*,
|
||||
i64 intKey,
|
||||
int bias,
|
||||
int *pRes
|
||||
|
||||
+6
-6
@@ -3829,7 +3829,7 @@ case OP_SeekGT: { /* jump, in3 */
|
||||
if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++;
|
||||
}
|
||||
}
|
||||
rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)iKey, 0, &res);
|
||||
rc = sqlite3BtreeMovetoIntkey(pC->uc.pCursor, (u64)iKey, 0, &res);
|
||||
pC->movetoTarget = iKey; /* Used by OP_Delete */
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto abort_due_to_error;
|
||||
@@ -3873,7 +3873,7 @@ case OP_SeekGT: { /* jump, in3 */
|
||||
{ int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
|
||||
#endif
|
||||
r.eqSeen = 0;
|
||||
rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, &r, 0, 0, &res);
|
||||
rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, &r, 0, &res);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
@@ -4042,7 +4042,7 @@ case OP_Found: { /* jump, in3 */
|
||||
}
|
||||
}
|
||||
}
|
||||
rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, pIdxKey, 0, 0, &res);
|
||||
rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, pIdxKey, 0, &res);
|
||||
sqlite3DbFree(db, pFree);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto abort_due_to_error;
|
||||
@@ -4136,7 +4136,7 @@ case OP_NotExists: /* jump, in3 */
|
||||
assert( pCrsr!=0 );
|
||||
res = 0;
|
||||
iKey = pIn3->u.i;
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
|
||||
rc = sqlite3BtreeMovetoIntkey(pCrsr, iKey, 0, &res);
|
||||
assert( rc==SQLITE_OK || res==0 );
|
||||
pC->movetoTarget = iKey; /* Used by OP_Delete */
|
||||
pC->nullRow = 0;
|
||||
@@ -4290,7 +4290,7 @@ case OP_NewRowid: { /* out2 */
|
||||
do{
|
||||
sqlite3_randomness(sizeof(v), &v);
|
||||
v &= (MAX_ROWID>>1); v++; /* Ensure that v is greater than zero */
|
||||
}while( ((rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)v,
|
||||
}while( ((rc = sqlite3BtreeMovetoIntkey(pC->uc.pCursor, (u64)v,
|
||||
0, &res))==SQLITE_OK)
|
||||
&& (res==0)
|
||||
&& (++cnt<100));
|
||||
@@ -5107,7 +5107,7 @@ case OP_IdxDelete: {
|
||||
r.nField = (u16)pOp->p3;
|
||||
r.default_rc = 0;
|
||||
r.aMem = &aMem[pOp->p2];
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, &res);
|
||||
if( rc ) goto abort_due_to_error;
|
||||
if( res==0 ){
|
||||
rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
|
||||
|
||||
+1
-1
@@ -3008,7 +3008,7 @@ static int SQLITE_NOINLINE handleDeferredMoveto(VdbeCursor *p){
|
||||
assert( p->deferredMoveto );
|
||||
assert( p->isTable );
|
||||
assert( p->eCurType==CURTYPE_BTREE );
|
||||
rc = sqlite3BtreeMovetoUnpacked(p->uc.pCursor, 0, p->movetoTarget, 0, &res);
|
||||
rc = sqlite3BtreeMovetoIntkey(p->uc.pCursor, p->movetoTarget, 0, &res);
|
||||
if( rc ) return rc;
|
||||
if( res!=0 ) return SQLITE_CORRUPT_BKPT;
|
||||
#ifdef SQLITE_TEST
|
||||
|
||||
Reference in New Issue
Block a user