]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Enhance the b-tree page sorting code to ensure that sqlite3PagerRekey() never
authordan <Dan Kennedy>
Sat, 10 Sep 2022 13:50:33 +0000 (13:50 +0000)
committerdan <Dan Kennedy>
Sat, 10 Sep 2022 13:50:33 +0000 (13:50 +0000)
overloads a page number and uses only the PENDING_BYTE page for temporary
storage.

FossilOrigin-Name: aa6a5b729782dee75f14ae4e780302c4446074c20d1eb300346fbe874eb64706

manifest
manifest.uuid
src/btree.c
src/pcache1.c

index 6cd2cdb2812acd54912291e444c816fbeb22dd8b..6af2203daeef8fc142fb06b6bc98897a3d564b92 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Enhance\san\sassert()\sto\simpose\sfor\stighter\sconstraints\son\sthe\soperation\sof\spcache.
-D 2022-09-07T20:14:38.920
+C Enhance\sthe\sb-tree\spage\ssorting\scode\sto\sensure\sthat\ssqlite3PagerRekey()\snever\noverloads\sa\spage\snumber\sand\suses\sonly\sthe\sPENDING_BYTE\spage\sfor\stemporary\nstorage.
+D 2022-09-10T13:50:33.163
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -510,7 +510,7 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf
 F src/backup.c a2891172438e385fdbe97c11c9745676bec54f518d4447090af97189fd8e52d7
 F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d
 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
-F src/btree.c b5a74c39d3123dadd190019c0afadd7f62b43dfe0712a39e9d0ff2fe26be5d93
+F src/btree.c 7f1dcdfc69595ec4927893c0aef44b2c5fe24f16bb7dee331b98414ac3eced98
 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22
 F src/btreeInt.h 8ce1332edd89dfd2461d561ac10a0ab5601c8e06200cb5230596c3caaf54482e
 F src/build.c 29fcc97af5197511788a571ed35a001eea472cbe3bcdbae88178e17fcafd4341
@@ -562,7 +562,7 @@ F src/pager.h f82e9844166e1585f5786837ddc7709966138ced17f568c16af7ccf946c2baa3
 F src/parse.y 8e67d820030d2655b9942ffe61c1e7e6b96cea2f2f72183533299393907d0564
 F src/pcache.c 5df59c993907b742dfac6aa9038d2515856bede56040a7640d39d06e1c93b494
 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
-F src/pcache1.c cfffa35ee38dd6a1d5f9f6a3d7b08e9756882589789894f4dbfd7a30617f91b0
+F src/pcache1.c 3e6267b17bae4cbaf02dfa08c4507794452991206862e3fc5c94d28313d32c18
 F src/pragma.c 404c0fe37b51f6def2c9ec6b07c80f0355673f0e74d720dc9a58a78725502417
 F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
 F src/prepare.c c62820c15dcb63013519c8e41d9f928d7478672cc902cfd0581c733c271dbf45
@@ -1978,9 +1978,9 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 1662eb07d8fa01457b3e3f37894234aae27c25a67059da968ab8cb599d3bd8f6
-Q +42105eb43a916a7cd839fa6c582eaffaef17f50b23c3e05142400c379feb73c7
-R 012d4db6d9dd0feee90f3cdbb4b5948b
-U drh
-Z cea974c1dce9d7ab515b2ee6bacd87f4
+P 461511cc99e5b1f936d0acbfcfe117c4ceb721a28eed50bb6db7a2244aedb599
+Q +5007742886bd20de20be3973737cf46b010359911615eb3da69cd262bd9a2435
+R 442893cbcb260f464928862f7b907724
+U dan
+Z b34a6024bd57313b837f90e9db41d0da
 # Remove this line to create a well-formed Fossil manifest.
index ffa7a6f92cffdbc3ed9a0678ff0ad7bd32ad6e05..8a4356b533545bad196ac910280e2d939377f618 100644 (file)
@@ -1 +1 @@
-461511cc99e5b1f936d0acbfcfe117c4ceb721a28eed50bb6db7a2244aedb599
\ No newline at end of file
+aa6a5b729782dee75f14ae4e780302c4446074c20d1eb300346fbe874eb64706
\ No newline at end of file
index facb951d3cbd79a7eb5b666525bea0a0b8904695..f1740dd88037f93073599493be9dc61a045dd559 100644 (file)
@@ -7904,8 +7904,6 @@ static int balance_nonroot(
   Pgno pgno;                   /* Temp var to store a page number in */
   u8 abDone[NB+2];             /* True after i'th new page is populated */
   Pgno aPgno[NB+2];            /* Page numbers of new pages before shuffling */
-  Pgno aPgOrder[NB+2];         /* Copy of aPgno[] used for sorting pages */
-  u16 aPgFlags[NB+2];          /* flags field of new pages before shuffling */
   CellArray b;                 /* Parsed information on cells being balanced */
 
   memset(abDone, 0, sizeof(abDone));
@@ -8329,42 +8327,39 @@ static int balance_nonroot(
   ** of the table is closer to a linear scan through the file. That in turn 
   ** helps the operating system to deliver pages from the disk more rapidly.
   **
-  ** An O(n^2) insertion sort algorithm is used, but since n is never more 
-  ** than (NB+2) (a small constant), that should not be a problem.
+  ** An O(N*N) sort algorithm is used, but since N is never more than NB+2
+  ** (5), that is not a performance concern.
   **
   ** When NB==3, this one optimization makes the database about 25% faster 
   ** for large insertions and deletions.
   */
   for(i=0; i<nNew; i++){
-    aPgOrder[i] = aPgno[i] = apNew[i]->pgno;
-    aPgFlags[i] = apNew[i]->pDbPage->flags;
-    for(j=0; j<i; j++){
-      if( NEVER(aPgno[j]==aPgno[i]) ){
-        /* This branch is taken if the set of sibling pages somehow contains
-        ** duplicate entries. This can happen if the database is corrupt. 
-        ** It would be simpler to detect this as part of the loop below, but
-        ** we do the detection here in order to avoid populating the pager
-        ** cache with two separate objects associated with the same
-        ** page number.  */
-        assert( CORRUPT_DB );
-        rc = SQLITE_CORRUPT_BKPT;
-        goto balance_cleanup;
-      }
-    }
+    aPgno[i] = apNew[i]->pgno;
+    assert( apNew[i]->pDbPage->flags & PGHDR_WRITEABLE );
+    assert( apNew[i]->pDbPage->flags & PGHDR_DIRTY );
   }
-  for(i=0; i<nNew; i++){
-    int iBest = 0;                /* aPgno[] index of page number to use */
-    for(j=1; j<nNew; j++){
-      if( aPgOrder[j]<aPgOrder[iBest] ) iBest = j;
-    }
-    pgno = aPgOrder[iBest];
-    aPgOrder[iBest] = 0xffffffff;
-    if( iBest!=i ){
-      if( iBest>i ){
-        sqlite3PagerRekey(apNew[iBest]->pDbPage, pBt->nPage+iBest+1, 0);
-      }
-      sqlite3PagerRekey(apNew[i]->pDbPage, pgno, aPgFlags[iBest]);
-      apNew[i]->pgno = pgno;
+  for(i=0; i<nNew-1; i++){
+    int iB = i;
+    for(j=i+1; j<nNew; j++){
+      if( apNew[j]->pgno < apNew[iB]->pgno ) iB = j;
+    }
+
+    /* If apNew[i] has a page number that is bigger than any of the
+    ** subsequence apNew[i] entries, then swap apNew[i] with the subsequent
+    ** entry that has the smallest page number (which we know to be
+    ** entry apNew[iB]).
+    */
+    if( iB!=i ){
+      Pgno pgnoA = apNew[i]->pgno;
+      Pgno pgnoB = apNew[iB]->pgno;
+      Pgno pgnoTemp = (PENDING_BYTE/pBt->pageSize)+1;
+      u16 fgA = apNew[i]->pDbPage->flags;
+      u16 fgB = apNew[iB]->pDbPage->flags;
+      sqlite3PagerRekey(apNew[i]->pDbPage, pgnoTemp, fgB);
+      sqlite3PagerRekey(apNew[iB]->pDbPage, pgnoA, fgA);
+      sqlite3PagerRekey(apNew[i]->pDbPage, pgnoB, fgB);
+      apNew[i]->pgno = pgnoB;
+      apNew[iB]->pgno = pgnoA;
     }
   }
 
index 82e6569182f09433ed4162ce69ff89c280acc974..ce595f2c201237591606f01d0b1976334bee8fda 100644 (file)
@@ -1129,7 +1129,7 @@ static void pcache1Rekey(
   assert( iOld!=iNew );               /* The page number really is changing */
 
   pcache1EnterMutex(pCache->pGroup);
-
+  
   assert( pcache1FetchNoMutex(p, iOld, 0)==pPage ); /* pPg really is iOld */
   hOld = iOld%pCache->nHash;
   pp = &pCache->apHash[hOld];