mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Split the sqlite3BtreeMovetoUnpacked() routine into two separate routines
sqlite3BtreeTableMoveto() and sqlite3BtreeIndexMoveto(), since we usually know the type of btree in advance. This results in less branching and better performance. FossilOrigin-Name: 3b0d34e5e5f9a16c3397e4551f3b534729b1b375770f05f6ed5847818b1f4c0b
This commit is contained in:
403
src/btree.c
403
src/btree.c
@@ -827,15 +827,13 @@ static int btreeMoveto(
|
||||
sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey);
|
||||
if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto moveto_done;
|
||||
}else{
|
||||
rc = sqlite3BtreeIndexMoveto(pCur, pIdxKey, pRes);
|
||||
}
|
||||
sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey);
|
||||
}else{
|
||||
pIdxKey = 0;
|
||||
}
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
|
||||
moveto_done:
|
||||
if( pIdxKey ){
|
||||
sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey);
|
||||
rc = sqlite3BtreeTableMoveto(pCur, nKey, bias, pRes);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -5421,12 +5419,8 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Move the cursor so that it points to an entry near the key
|
||||
** specified by pIdxKey or intKey. Return a success code.
|
||||
**
|
||||
** For INTKEY tables, the intKey parameter is used. pIdxKey
|
||||
** must be NULL. For index tables, pIdxKey is used and intKey
|
||||
** is ignored.
|
||||
/* Move the cursor so that it points to an entry in a table (a.k.a INTKEY)
|
||||
** table near the key intKey. Return a success code.
|
||||
**
|
||||
** If an exact match is not found, then the cursor is always
|
||||
** left pointing at a leaf page which would hold the entry if it
|
||||
@@ -5439,39 +5433,32 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
|
||||
** *pRes is as follows:
|
||||
**
|
||||
** *pRes<0 The cursor is left pointing at an entry that
|
||||
** is smaller than intKey/pIdxKey or if the table is empty
|
||||
** is smaller than intKey or if the table is empty
|
||||
** and the cursor is therefore left point to nothing.
|
||||
**
|
||||
** *pRes==0 The cursor is left pointing at an entry that
|
||||
** exactly matches intKey/pIdxKey.
|
||||
** exactly matches intKey.
|
||||
**
|
||||
** *pRes>0 The cursor is left pointing at an entry that
|
||||
** is larger than intKey/pIdxKey.
|
||||
**
|
||||
** For index tables, the pIdxKey->eqSeen field is set to 1 if there
|
||||
** exists an entry in the table that exactly matches pIdxKey.
|
||||
** is larger than intKey.
|
||||
*/
|
||||
int sqlite3BtreeMovetoUnpacked(
|
||||
int sqlite3BtreeTableMoveto(
|
||||
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 */
|
||||
){
|
||||
int rc;
|
||||
RecordCompare xRecordCompare;
|
||||
|
||||
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) );
|
||||
assert( pCur->pKeyInfo==0 );
|
||||
assert( pCur->eState!=CURSOR_VALID || 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->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0 ){
|
||||
if( pCur->info.nKey==intKey ){
|
||||
*pRes = 0;
|
||||
return SQLITE_OK;
|
||||
@@ -5506,16 +5493,149 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
pCur->pBtree->nSeek++; /* Performance measurement during testing */
|
||||
#endif
|
||||
|
||||
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 */
|
||||
rc = moveToRoot(pCur);
|
||||
if( rc ){
|
||||
if( rc==SQLITE_EMPTY ){
|
||||
assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
|
||||
*pRes = -1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
assert( pCur->pPage );
|
||||
assert( pCur->pPage->isInit );
|
||||
assert( pCur->eState==CURSOR_VALID );
|
||||
assert( pCur->pPage->nCell > 0 );
|
||||
assert( pCur->iPage==0 || pCur->apPage[0]->intKey==pCur->curIntKey );
|
||||
assert( pCur->curIntKey );
|
||||
|
||||
for(;;){
|
||||
int lwr, upr, idx, c;
|
||||
Pgno chldPg;
|
||||
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
|
||||
** 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->ix = (u16)idx;
|
||||
for(;;){
|
||||
i64 nCellKey;
|
||||
pCell = findCellPastPtr(pPage, idx);
|
||||
if( pPage->intKeyLeaf ){
|
||||
while( 0x80 <= *(pCell++) ){
|
||||
if( pCell>=pPage->aDataEnd ){
|
||||
return SQLITE_CORRUPT_PAGE(pPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
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->ix = (u16)idx;
|
||||
if( !pPage->leaf ){
|
||||
lwr = idx;
|
||||
goto moveto_table_next_layer;
|
||||
}else{
|
||||
pCur->curFlags |= BTCF_ValidNKey;
|
||||
pCur->info.nKey = nCellKey;
|
||||
pCur->info.nSize = 0;
|
||||
*pRes = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
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->ix<pCur->pPage->nCell );
|
||||
pCur->ix = (u16)idx;
|
||||
*pRes = c;
|
||||
rc = SQLITE_OK;
|
||||
goto moveto_table_finish;
|
||||
}
|
||||
moveto_table_next_layer:
|
||||
if( lwr>=pPage->nCell ){
|
||||
chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
|
||||
}else{
|
||||
chldPg = get4byte(findCell(pPage, lwr));
|
||||
}
|
||||
pCur->ix = (u16)lwr;
|
||||
rc = moveToChild(pCur, chldPg);
|
||||
if( rc ) break;
|
||||
}
|
||||
moveto_table_finish:
|
||||
pCur->info.nSize = 0;
|
||||
assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Move the cursor so that it points to an entry in an index table
|
||||
** near the key pIdxKey. Return a success code.
|
||||
**
|
||||
** If an exact match is not found, then the cursor is always
|
||||
** left pointing at a leaf page which would hold the entry if it
|
||||
** were present. The cursor might point to an entry that comes
|
||||
** before or after the key.
|
||||
**
|
||||
** An integer is written into *pRes which is the result of
|
||||
** comparing the key with the entry to which the cursor is
|
||||
** pointing. The meaning of the integer written into
|
||||
** *pRes is as follows:
|
||||
**
|
||||
** *pRes<0 The cursor is left pointing at an entry that
|
||||
** is smaller than pIdxKey or if the table is empty
|
||||
** and the cursor is therefore left point to nothing.
|
||||
**
|
||||
** *pRes==0 The cursor is left pointing at an entry that
|
||||
** exactly matches pIdxKey.
|
||||
**
|
||||
** *pRes>0 The cursor is left pointing at an entry that
|
||||
** is larger than pIdxKey.
|
||||
**
|
||||
** The pIdxKey->eqSeen field is set to 1 if there
|
||||
** exists an entry in the table that exactly matches pIdxKey.
|
||||
*/
|
||||
int sqlite3BtreeIndexMoveto(
|
||||
BtCursor *pCur, /* The cursor to be moved */
|
||||
UnpackedRecord *pIdxKey, /* Unpacked index key */
|
||||
int *pRes /* Write search results here */
|
||||
){
|
||||
int rc;
|
||||
RecordCompare xRecordCompare;
|
||||
|
||||
assert( cursorOwnsBtShared(pCur) );
|
||||
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
|
||||
assert( pRes );
|
||||
assert( pCur->pKeyInfo!=0 );
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
pCur->pBtree->nSeek++; /* Performance measurement during testing */
|
||||
#endif
|
||||
|
||||
xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
|
||||
pIdxKey->errCode = 0;
|
||||
assert( pIdxKey->default_rc==1
|
||||
|| pIdxKey->default_rc==0
|
||||
|| pIdxKey->default_rc==-1
|
||||
);
|
||||
|
||||
rc = moveToRoot(pCur);
|
||||
if( rc ){
|
||||
@@ -5548,130 +5668,92 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
assert( pPage->intKey==(pIdxKey==0) );
|
||||
lwr = 0;
|
||||
upr = pPage->nCell-1;
|
||||
assert( biasRight==0 || biasRight==1 );
|
||||
idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
|
||||
idx = upr>>1; /* idx = (lwr+upr)/2; */
|
||||
pCur->ix = (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_PAGE(pPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
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->ix = (u16)idx;
|
||||
if( !pPage->leaf ){
|
||||
lwr = idx;
|
||||
goto moveto_next_layer;
|
||||
}else{
|
||||
pCur->curFlags |= BTCF_ValidNKey;
|
||||
pCur->info.nKey = nCellKey;
|
||||
pCur->info.nSize = 0;
|
||||
*pRes = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
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;
|
||||
const int nOverrun = 18; /* Size of the overrun padding */
|
||||
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 || nCell/pCur->pBt->usableSize>pCur->pBt->nPage ){
|
||||
rc = SQLITE_CORRUPT_PAGE(pPage);
|
||||
goto moveto_finish;
|
||||
}
|
||||
pCellKey = sqlite3Malloc( nCell+nOverrun );
|
||||
if( pCellKey==0 ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
goto moveto_finish;
|
||||
}
|
||||
pCur->ix = (u16)idx;
|
||||
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
|
||||
memset(((u8*)pCellKey)+nCell,0,nOverrun); /* Fix uninit warnings */
|
||||
pCur->curFlags &= ~BTCF_ValidOvfl;
|
||||
if( rc ){
|
||||
sqlite3_free(pCellKey);
|
||||
goto moveto_finish;
|
||||
}
|
||||
c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
|
||||
/* 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;
|
||||
const int nOverrun = 18; /* Size of the overrun padding */
|
||||
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 || nCell/pCur->pBt->usableSize>pCur->pBt->nPage ){
|
||||
rc = SQLITE_CORRUPT_PAGE(pPage);
|
||||
goto moveto_index_finish;
|
||||
}
|
||||
pCellKey = sqlite3Malloc( nCell+nOverrun );
|
||||
if( pCellKey==0 ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
goto moveto_index_finish;
|
||||
}
|
||||
pCur->ix = (u16)idx;
|
||||
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
|
||||
memset(((u8*)pCellKey)+nCell,0,nOverrun); /* Fix uninit warnings */
|
||||
pCur->curFlags &= ~BTCF_ValidOvfl;
|
||||
if( rc ){
|
||||
sqlite3_free(pCellKey);
|
||||
goto moveto_index_finish;
|
||||
}
|
||||
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->ix = (u16)idx;
|
||||
if( pIdxKey->errCode ) rc = SQLITE_CORRUPT_BKPT;
|
||||
goto moveto_finish;
|
||||
}
|
||||
if( lwr>upr ) break;
|
||||
assert( lwr+upr>=0 );
|
||||
idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */
|
||||
c = sqlite3VdbeRecordCompare(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->ix = (u16)idx;
|
||||
if( pIdxKey->errCode ) rc = SQLITE_CORRUPT_BKPT;
|
||||
goto moveto_index_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( pPage->isInit );
|
||||
@@ -5680,9 +5762,8 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
pCur->ix = (u16)idx;
|
||||
*pRes = c;
|
||||
rc = SQLITE_OK;
|
||||
goto moveto_finish;
|
||||
goto moveto_index_finish;
|
||||
}
|
||||
moveto_next_layer:
|
||||
if( lwr>=pPage->nCell ){
|
||||
chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
|
||||
}else{
|
||||
@@ -5692,7 +5773,7 @@ moveto_next_layer:
|
||||
rc = moveToChild(pCur, chldPg);
|
||||
if( rc ) break;
|
||||
}
|
||||
moveto_finish:
|
||||
moveto_index_finish:
|
||||
pCur->info.nSize = 0;
|
||||
assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
|
||||
return rc;
|
||||
@@ -8798,7 +8879,8 @@ int sqlite3BtreeInsert(
|
||||
** to an adjacent cell. Move the cursor so that it is pointing either
|
||||
** to the cell to be overwritten or an adjacent cell.
|
||||
*/
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc);
|
||||
rc = sqlite3BtreeTableMoveto(pCur, pX->nKey,
|
||||
(flags & BTREE_APPEND)!=0, &loc);
|
||||
if( rc ) return rc;
|
||||
}
|
||||
}else{
|
||||
@@ -8825,9 +8907,10 @@ int sqlite3BtreeInsert(
|
||||
r.r1 = 0;
|
||||
r.r2 = 0;
|
||||
r.eqSeen = 0;
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc);
|
||||
rc = sqlite3BtreeIndexMoveto(pCur, &r, &loc);
|
||||
}else{
|
||||
rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc);
|
||||
rc = btreeMoveto(pCur, pX->pKey, pX->nKey,
|
||||
(flags & BTREE_APPEND)!=0, &loc);
|
||||
}
|
||||
if( rc ) return rc;
|
||||
}
|
||||
|
Reference in New Issue
Block a user