]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix a recently introduced problem with deleting entries from index tables. (CVS 5754)
authordanielk1977 <danielk1977@noemail.net>
Tue, 30 Sep 2008 09:31:45 +0000 (09:31 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Tue, 30 Sep 2008 09:31:45 +0000 (09:31 +0000)
FossilOrigin-Name: 83c064cae481ca95b7107e22e98fc599fe85a2da

manifest
manifest.uuid
src/btree.c

index 946638415153446a9a3ca33c50eb0bdaa5b6bff2..4f48a745d16e09092447c7d51bc6587c7ee7ace4 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Misc\sclean\sup.\s\sWrapped\sa\sCE\sonly\svariable\sin\sif-defs.\sChanged\sto\sonly\sprovide\scache\shint\sfor\sCE\sbuilds\s(as\sthis\sprevents\sCE\sfrom\scompressing\sthe\sfile.)\sPerformance\stesting\son\sXP\sand\sVista\sshowed\scaching\shint\shad\slittle\seffect\swhen\sthe\sDB\ssize\swas\smuch\ssmaller\sthan\sthe\sO/S\sdisk\scache\ssize,\sand\sprovided\sonly\smarginal\sbenefit\swhen\sthe\sDB\ssize\swas\smuch\slarger\sthan\sthe\scache.\s\sOn\sVista,\soverall\ssystem\sperformance\swas\shurt\sfor\svery\slarge\sDBs.\s\sTicket\s#3387.\s(CVS\s5753)
-D 2008-09-30T04:20:08
+C Fix\sa\srecently\sintroduced\sproblem\swith\sdeleting\sentries\sfrom\sindex\stables.\s(CVS\s5754)
+D 2008-09-30T09:31:45
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in e4ab842f9a64ef61d57093539a8aab76b12810db
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -99,7 +99,7 @@ F src/attach.c db3f4a60538733c1e4dcb9d0217a6e0d6ccd615b
 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
 F src/bitvec.c 95c86bd18d8fedf0533f5af196192546e10a7e7d
 F src/btmutex.c 709cad2cdca0afd013f0f612363810e53f59ec53
-F src/btree.c df02edb06f8fcb53d607a338d77434c4a3bffe7a
+F src/btree.c 2e5cf91c3f342fa611bfd6f0250c31b432fbdd90
 F src/btree.h 6371c5e599fab391a150c96afbc10062b276d107
 F src/btreeInt.h 3e93c0a6f363bbf68fdd975620f4d3671b6cf7bc
 F src/build.c 160c71acca8f643f436ed6c1ee2f684c88df4dfe
@@ -637,7 +637,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P 78d075ff38d96cc58659a7097dec0e49402aa960
-R 39be9f2940749141be589318f7d2a538
-U shane
-Z b381b1aa9c52e2148aadad6fea9866f7
+P 15dd0169a4c5e2ff9e3894eec10799cb89d462e5
+R 67ac196eea416fb3e08d66e37fb1b4f0
+U danielk1977
+Z 769068257f0c5361c027fdd2793aa895
index 192288f9710c22ea49b80080309a1990c7488885..570c8a0f6119e94376afb453e8b4447878d5fa48 100644 (file)
@@ -1 +1 @@
-15dd0169a4c5e2ff9e3894eec10799cb89d462e5
\ No newline at end of file
+83c064cae481ca95b7107e22e98fc599fe85a2da
\ No newline at end of file
index f45a6fde0d6ba173c5d1f9913e4286c9ef641cfe..655a63d3f5a2fb2295bfbac68750df05a174f23b 100644 (file)
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btree.c,v 1.520 2008/09/29 16:41:32 danielk1977 Exp $
+** $Id: btree.c,v 1.521 2008/09/30 09:31:45 danielk1977 Exp $
 **
 ** This file implements a external (disk-based) database using BTrees.
 ** See the header comment on "btreeInt.h" for additional information.
@@ -5883,7 +5883,6 @@ int sqlite3BtreeDelete(BtCursor *pCur){
     */
     BtCursor leafCur;
     MemPage *pLeafPage;
-    int iLeafIdx;
 
     unsigned char *pNext;
     int notUsed;
@@ -5892,16 +5891,17 @@ int sqlite3BtreeDelete(BtCursor *pCur){
     sqlite3BtreeGetTempCursor(pCur, &leafCur);
     rc = sqlite3BtreeNext(&leafCur, &notUsed);
     if( rc==SQLITE_OK ){
+      assert( leafCur.aiIdx[leafCur.iPage]==0 );
       pLeafPage = leafCur.apPage[leafCur.iPage];
-      iLeafIdx = leafCur.aiIdx[leafCur.iPage];
       rc = sqlite3PagerWrite(pLeafPage->pDbPage);
     }
     if( rc==SQLITE_OK ){
+      int leafCursorInvalid = 0;
       u16 szNext;
       TRACE(("DELETE: table=%d delete internal from %d replace from leaf %d\n",
          pCur->pgnoRoot, pPage->pgno, pLeafPage->pgno));
       dropCell(pPage, idx, cellSizePtr(pPage, pCell));
-      pNext = findCell(pLeafPage, iLeafIdx);
+      pNext = findCell(pLeafPage, 0);
       szNext = cellSizePtr(pLeafPage, pNext);
       assert( MX_CELL_SIZE(pBt)>=szNext+4 );
       allocateTempSpace(pBt);
@@ -5912,12 +5912,66 @@ int sqlite3BtreeDelete(BtCursor *pCur){
       if( rc==SQLITE_OK ){
         rc = insertCell(pPage, idx, pNext-4, szNext+4, tempCell, 0);
       }
+
+      if( (pPage->nOverflow>0 || (pPage->nFree > pBt->usableSize*2/3)) &&
+          (pLeafPage->nFree+2+szNext > pBt->usableSize*2/3)
+      ){
+        /* This branch is taken if the internal node is now either over or
+        ** underfull and the leaf node will be underfull after the just cell 
+        ** copied to the internal node is deleted from it. This is a special
+        ** case because the call to balance() to correct the internal node
+        ** may change the tree structure and invalidate the contents of
+        ** the leafCur.apPage[] and leafCur.aiIdx[] arrays, which will be
+        ** used by the balance() required to correct the underfull leaf
+        ** node.
+        **
+        ** The formula used in the expression above are based on facets of
+        ** the SQLite file-format that do not change over time.
+        */
+        leafCursorInvalid = 1;
+      }        
+
       if( rc==SQLITE_OK ){
         put4byte(findOverflowCell(pPage, idx), pgnoChild);
         rc = balance(pCur, 0);
       }
+
+      if( rc==SQLITE_OK && leafCursorInvalid ){
+        /* The leaf-node is now underfull and so the tree needs to be 
+        ** rebalanced. However, the balance() operation on the internal
+        ** node above may have modified the structure of the B-Tree and
+        ** so the current contents of leafCur.apPage[] and leafCur.aiIdx[]
+        ** may not be trusted.
+        **
+        ** It is not possible to copy the ancestry from pCur, as the same
+        ** balance() call has invalidated the pCur->apPage[] and aiIdx[]
+        ** arrays. 
+       **
+       ** The call to saveCursorPosition() below internally saves the 
+       ** key that leafCur is currently pointing to. Currently, there
+       ** are two copies of that key in the tree - one here on the leaf
+       ** page and one on some internal node in the tree. The copy on
+       ** the leaf node is always the next key in tree-order after the 
+       ** copy on the internal node. So, the call to sqlite3BtreeNext()
+       ** calls restoreCursorPosition() to point the cursor to the copy
+       ** stored on the internal node, then advances to the next entry,
+       ** which happens to be the copy of the key on the internal node.
+       ** Net effect: leafCur is pointing back where
+        */
+      #ifndef NDEBUG
+        Pgno leafPgno = pLeafPage->pgno;
+      #endif
+        rc = saveCursorPosition(&leafCur);
+        if( rc==SQLITE_OK ){
+          rc = sqlite3BtreeNext(&leafCur, &notUsed);
+        }
+        pLeafPage = leafCur.apPage[leafCur.iPage];
+        assert( pLeafPage->pgno==leafPgno );
+        assert( leafCur.aiIdx[leafCur.iPage]==0 );
+      }
+
       if( rc==SQLITE_OK ){
-        dropCell(pLeafPage, iLeafIdx, szNext);
+        dropCell(pLeafPage, 0, szNext);
         rc = balance(&leafCur, 0);
       }
     }
@@ -7026,7 +7080,7 @@ static int btreeCopyFile(Btree *pTo, Btree *pFrom){
           }
 
           memcpy(zTo, zFrom, nCopy);
-         sqlite3PagerUnref(pFromPage);
+          sqlite3PagerUnref(pFromPage);
         }
       }