aboutsummaryrefslogtreecommitdiff
path: root/src/btree.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2018-05-03 03:59:02 +0000
committerdrh <drh@noemail.net>2018-05-03 03:59:02 +0000
commit3de5d16cf7df698599136d4a6695c97dbb603c2d (patch)
tree56f45fac56fc6ac5217b72a1daa193d7984c8737 /src/btree.c
parent85a40ebc03676fd5b774fad42ae7a88d419fe4dc (diff)
downloadsqlite-3de5d16cf7df698599136d4a6695c97dbb603c2d.tar.gz
sqlite-3de5d16cf7df698599136d4a6695c97dbb603c2d.zip
The sqlite3BtreeInsert() routine tries to overwrite an existing cell with
modified content if the new content is the same size. Pages are only dirtied if they change. This prototype works some, but still has issues. FossilOrigin-Name: 489451b378819621537231c1c8a07704437e11c1f5384fd53b09f3977d2213a4
Diffstat (limited to 'src/btree.c')
-rw-r--r--src/btree.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/btree.c b/src/btree.c
index 700138efc..0a8c17221 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -8152,6 +8152,83 @@ static int balance(BtCursor *pCur){
return rc;
}
+/* Overwrite content from pX into pDest. Only do the write if the
+** content is different from what is already there.
+*/
+static int btreeOverwriteContent(
+ MemPage *pPage, /* MemPage on which writing will occur */
+ u8 *pDest, /* Pointer to the place to start writing */
+ const BtreePayload *pX, /* Source of data to write */
+ int iOffset, /* Offset of first byte to write */
+ int iAmt /* Number of bytes to be written */
+){
+ int nData = pX->nData - iOffset;
+ if( nData<=0 ){
+ /* Overwritting with zeros */
+ int i;
+ for(i=0; i<iAmt && pDest[i]==0; i++){}
+ if( i<iAmt ){
+ int rc = sqlite3PagerWrite(pPage->pDbPage);
+ if( rc ) return rc;
+ memset(pDest + i, 0, iAmt - i);
+ }
+ }else{
+ if( nData<iAmt ){
+ /* Mixed read data and zeros at the end. Make a recursive call
+ ** to write the zeros then fall through to write the real data */
+ btreeOverwriteContent(pPage, pDest+nData, pX, iOffset+nData, iAmt-nData);
+ iAmt = nData;
+ }
+ if( memcmp(pDest, ((u8*)pX->pData) + iOffset, iAmt)!=0 ){
+ int rc = sqlite3PagerWrite(pPage->pDbPage);
+ if( rc ) return rc;
+ memcpy(pDest, ((u8*)pX->pData) + iOffset, iAmt);
+ }
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Overwrite the cell that cursor pCur is pointing to with fresh content
+** contained in pX.
+*/
+static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
+ int iOffset; /* Next byte of pX->pData to write */
+ int nTotal = pX->nData + pX->nZero; /* Total bytes of to write */
+ int rc; /* Return code */
+ MemPage *pPage = pCur->pPage; /* Page being written */
+ BtShared *pBt; /* Btree */
+ Pgno ovflPgno; /* Next overflow page to write */
+ u32 ovflPageSize; /* Size to write on overflow page */
+
+ /* Overwrite the local portion first */
+ rc = btreeOverwriteContent(pPage, pCur->info.pPayload, pX,
+ 0, pCur->info.nLocal);
+ if( rc ) return rc;
+ if( pCur->info.nLocal==nTotal ) return SQLITE_OK;
+
+ /* Now overwrite the overflow pages */
+ iOffset = pCur->info.nLocal;
+ ovflPgno = get4byte(pCur->info.pPayload + iOffset);
+ pBt = pPage->pBt;
+ ovflPageSize = pBt->usableSize - 4;
+ do{
+ rc = btreeGetPage(pBt, ovflPgno, &pPage, 0);
+ if( rc ) return rc;
+ if( iOffset+ovflPageSize>nTotal ){
+ ovflPgno = get4byte(pPage->aData + ovflPageSize);
+ }else{
+ ovflPageSize = nTotal - iOffset;
+ }
+ rc = btreeOverwriteContent(pPage, pPage->aData, pX,
+ iOffset, ovflPageSize);
+ if( rc ) return rc;
+ iOffset += ovflPageSize;
+ sqlite3PagerUnref(pPage->pDbPage);
+ }while( iOffset<nTotal );
+ return SQLITE_OK;
+}
+
/*
** Insert a new record into the BTree. The content of the new record
@@ -8250,6 +8327,11 @@ int sqlite3BtreeInsert(
** new row onto the end, set the "loc" to avoid an unnecessary
** btreeMoveto() call */
if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){
+ /* The current is currently pointing to the entry that is to be
+ ** overwritten */
+ if( pCur->info.nPayload==pX->nData+pX->nZero ){
+ return btreeOverwriteCell(pCur, pX);
+ }
loc = 0;
}else if( loc==0 ){
rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc);