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

In sqlite3BtreeInsert() when replacing a re-existing row, try to overwrite

the cell directly rather than deallocate and reallocate the cell.

FossilOrigin-Name: 0b86fbca6615ccf1f3a62614db577a8acbec6d9e
This commit is contained in:
drh
2016-12-09 17:32:51 +00:00
parent 55092c1504
commit 80159da6c6
3 changed files with 28 additions and 25 deletions

View File

@@ -5996,30 +5996,28 @@ static void freePage(MemPage *pPage, int *pRC){
static int clearCell(
MemPage *pPage, /* The page that contains the Cell */
unsigned char *pCell, /* First byte of the Cell */
u16 *pnSize /* Write the size of the Cell here */
CellInfo *pInfo /* Size information about the cell */
){
BtShared *pBt = pPage->pBt;
CellInfo info;
Pgno ovflPgno;
int rc;
int nOvfl;
u32 ovflPageSize;
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
pPage->xParseCell(pPage, pCell, &info);
*pnSize = info.nSize;
if( info.nLocal==info.nPayload ){
pPage->xParseCell(pPage, pCell, pInfo);
if( pInfo->nLocal==pInfo->nPayload ){
return SQLITE_OK; /* No overflow pages. Return without doing anything */
}
if( pCell+info.nSize-1 > pPage->aData+pPage->maskPage ){
if( pCell+pInfo->nSize-1 > pPage->aData+pPage->maskPage ){
return SQLITE_CORRUPT_BKPT; /* Cell extends past end of page */
}
ovflPgno = get4byte(pCell + info.nSize - 4);
ovflPgno = get4byte(pCell + pInfo->nSize - 4);
assert( pBt->usableSize > 4 );
ovflPageSize = pBt->usableSize - 4;
nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize;
nOvfl = (pInfo->nPayload - pInfo->nLocal + ovflPageSize - 1)/ovflPageSize;
assert( nOvfl>0 ||
(CORRUPT_DB && (info.nPayload + ovflPageSize)<ovflPageSize)
(CORRUPT_DB && (pInfo->nPayload + ovflPageSize)<ovflPageSize)
);
while( nOvfl-- ){
Pgno iNext = 0;
@@ -8052,7 +8050,7 @@ int sqlite3BtreeInsert(
assert( szNew <= MX_CELL_SIZE(pBt) );
idx = pCur->aiIdx[pCur->iPage];
if( loc==0 ){
u16 szOld;
CellInfo info;
assert( idx<pPage->nCell );
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ){
@@ -8062,8 +8060,13 @@ int sqlite3BtreeInsert(
if( !pPage->leaf ){
memcpy(newCell, oldCell, 4);
}
rc = clearCell(pPage, oldCell, &szOld);
dropCell(pPage, idx, szOld, &rc);
rc = clearCell(pPage, oldCell, &info);
if( info.nSize==szNew && info.nLocal==info.nPayload ){
/* Overwrite the old cell with the new */
memcpy(oldCell, newCell, szNew);
return SQLITE_OK;
}
dropCell(pPage, idx, info.nSize, &rc);
if( rc ) goto end_insert;
}else if( loc<0 && pPage->nCell>0 ){
assert( pPage->leaf );
@@ -8139,7 +8142,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
unsigned char *pCell; /* Pointer to cell to delete */
int iCellIdx; /* Index of cell to delete */
int iCellDepth; /* Depth of node containing pCell */
u16 szCell; /* Size of the cell being deleted */
CellInfo info; /* Size of the cell being deleted */
int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */
u8 bPreserve = flags & BTREE_SAVEPOSITION; /* Keep cursor valid */
@@ -8211,8 +8214,8 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** itself from within the page. */
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ) return rc;
rc = clearCell(pPage, pCell, &szCell);
dropCell(pPage, iCellIdx, szCell, &rc);
rc = clearCell(pPage, pCell, &info);
dropCell(pPage, iCellIdx, info.nSize, &rc);
if( rc ) return rc;
/* If the cell deleted was not located on a leaf page, then the cursor
@@ -8462,7 +8465,7 @@ static int clearDatabasePage(
unsigned char *pCell;
int i;
int hdr;
u16 szCell;
CellInfo info;
assert( sqlite3_mutex_held(pBt->mutex) );
if( pgno>btreePagecount(pBt) ){
@@ -8482,7 +8485,7 @@ static int clearDatabasePage(
rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
if( rc ) goto cleardatabasepage_out;
}
rc = clearCell(pPage, pCell, &szCell);
rc = clearCell(pPage, pCell, &info);
if( rc ) goto cleardatabasepage_out;
}
if( !pPage->leaf ){