]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Simplification of PRAGMA integrity_check logic. Make sure that the depth
authordrh <drh@noemail.net>
Wed, 1 Jul 2015 17:53:49 +0000 (17:53 +0000)
committerdrh <drh@noemail.net>
Wed, 1 Jul 2015 17:53:49 +0000 (17:53 +0000)
of the right-most subtree is correct.  Size reduction and performance increase,
with no change in output.

FossilOrigin-Name: 550705fcb64e7ad637686e47cabe2621d65851bf

manifest
manifest.uuid
src/btree.c
src/btreeInt.h
src/pager.c
src/pager.h

index ad6e53acd509382cb6ac52b2d235dacd92cda6b1..c6b3a9a01057c14908bcd9086a2f7fc52bc1c9cd 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\ssome\sharmless\scompiler\swarnings.
-D 2015-07-01T04:08:40.538
+C Simplification\sof\sPRAGMA\sintegrity_check\slogic.\s\sMake\ssure\sthat\sthe\sdepth\nof\sthe\sright-most\ssubtree\sis\scorrect.\s\sSize\sreduction\sand\sperformance\sincrease,\nwith\sno\schange\sin\soutput.
+D 2015-07-01T17:53:49.435
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 285a0a234ed7610d431d91671c136098c2bd86a9
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -269,9 +269,9 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
 F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3
 F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d
 F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
-F src/btree.c 075ce6ddce9e66277c898f5b6a44a8a7c61c8125
+F src/btree.c e283de2f9da7ec5e47bedcd442a66a671aa2e118
 F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
-F src/btreeInt.h c54d380cb262549c4176e0d665518cc1a3861bdf
+F src/btreeInt.h 2ad754dd4528baa8d0946a593cc373b890bf859e
 F src/build.c b3f15255d5b16e42dafeaa638fd4f8a47c94ed70
 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
 F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
@@ -314,8 +314,8 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
 F src/os_unix.c 23eb5f56fac54d8fe0cb204291f3b3b2d94f23fc
 F src/os_win.c 27cc135e2d0b8b1e2e4944db1e2669a6a18fa0f8
 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
-F src/pager.c 922d8ea28387b79a117488da06ee84f77d50d71e
-F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77
+F src/pager.c aa916ca28606ccf4b6877dfc2b643ccbca86589f
+F src/pager.h 6d435f563b3f7fcae4b84433b76a6ac2730036e2
 F src/parse.y 6d60dda8f8d418b6dc034f1fbccd816c459983a8
 F src/pcache.c cde06aa50962595e412d497e22fd2e07878ba1f0
 F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9
@@ -1364,7 +1364,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 59ad912c4c1f858e04d27b1b8f25581a5f6e5daf
-R 71a875c7f3b6312a533d9c1fd4d005d9
+P 307195c8709d7fd2a642baa8011eb0c88cfdc0ac
+R 1440540aa3867982699c114f203dbd2b
 U drh
-Z 39cb6954bdcd951136843b690dd37c51
+Z 4a2c86e34c201f78bc5202943cc67b23
index 71a9643813d9fdf4a54a522aa4352e1d2037bda4..a2d7952053f9a37b920d562d92f57dd24b98ecfb 100644 (file)
@@ -1 +1 @@
-307195c8709d7fd2a642baa8011eb0c88cfdc0ac
\ No newline at end of file
+550705fcb64e7ad637686e47cabe2621d65851bf
\ No newline at end of file
index a8e5beb22741c2b28739ec5f2ed62424a21da645..a34c84fbcd542b8b8c6cc725f9dbc804b5614c19 100644 (file)
@@ -8924,14 +8924,10 @@ static int btreeHeapPull(u32 *aHeap, u32 *pOut){
 **
 **      1.  Make sure that cells and freeblocks do not overlap
 **          but combine to completely cover the page.
-**  NO  2.  Make sure cell keys are in order.
-**  NO  3.  Make sure no key is less than or equal to zLowerBound.
-**  NO  4.  Make sure no key is greater than or equal to zUpperBound.
-**      5.  Check the integrity of overflow pages.
-**      6.  Recursively call checkTreePage on all children.
-**      7.  Verify that the depth of all children is the same.
-**      8.  Make sure this page is at least 33% full or else it is
-**          the root of the tree.
+**      2.  Make sure integer cell keys are in order.
+**      3.  Check the integrity of overflow pages.
+**      4.  Recursively call checkTreePage on all children.
+**      5.  Verify that the depth of all children is the same.
 */
 static int checkTreePage(
   IntegrityCk *pCheck,  /* Context for the sanity check */
@@ -8939,7 +8935,7 @@ static int checkTreePage(
   i64 *pnParentMinKey, 
   i64 *pnParentMaxKey
 ){
-  MemPage *pPage;
+  MemPage *pPage = 0;
   int i, rc, depth, d2, pgno, cnt;
   int hdr, cellStart;
   int nCell;
@@ -8976,7 +8972,6 @@ static int checkTreePage(
     assert( rc==SQLITE_CORRUPT );  /* The only possible error from InitPage */
     checkAppendMsg(pCheck,
                    "btreeInitPage() returns error code %d", rc);
-    releasePage(pPage);
     depth = -1;
     goto end_of_check;
   }
@@ -8984,6 +8979,7 @@ static int checkTreePage(
   /* Check out all the cells.
   */
   depth = 0;
+  pCheck->zPfx = "On tree page %d cell %d: ";
   for(i=0; i<pPage->nCell && pCheck->mxErr; i++){
     u8 *pCell;
     u32 sz;
@@ -8991,8 +8987,6 @@ static int checkTreePage(
 
     /* Check payload overflow pages
     */
-    pCheck->zPfx = "On tree page %d cell %d: ";
-    pCheck->v1 = iPage;
     pCheck->v2 = i;
     pCell = findCell(pPage,i);
     pPage->xParseCell(pPage, pCell, &info);
@@ -9041,20 +9035,21 @@ static int checkTreePage(
   if( !pPage->leaf ){
     pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
     pCheck->zPfx = "On page %d at right child: ";
-    pCheck->v1 = iPage;
 #ifndef SQLITE_OMIT_AUTOVACUUM
     if( pBt->autoVacuum ){
       checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage);
     }
 #endif
-    checkTreePage(pCheck, pgno, NULL, !pPage->nCell?NULL:&nMaxKey);
+    d2 = checkTreePage(pCheck, pgno, NULL, !pPage->nCell?NULL:&nMaxKey);
+    if( d2!=depth && iPage!=1 ){
+      checkAppendMsg(pCheck, "Child page depth differs");
+    }
   }
  
   /* For intKey leaf pages, check that the min/max keys are in order
   ** with any left/parent/right pages.
   */
   pCheck->zPfx = "Page %d: ";
-  pCheck->v1 = iPage;
   if( pPage->leaf && pPage->intKey ){
     /* if we are a left child page */
     if( pnParentMinKey ){
@@ -9092,14 +9087,12 @@ static int checkTreePage(
   */
   data = pPage->aData;
   hdr = pPage->hdrOffset;
-  heap = (u32*)sqlite3PageMalloc( pBt->pageSize );
+  heap = pCheck->heap;
+  heap[0] = 0;
   pCheck->zPfx = 0;
-  if( heap==0 ){
-    pCheck->mallocFailed = 1;
-  }else{
+  {
     int contentOffset = get2byteNotZero(&data[hdr+5]);
     assert( contentOffset<=usableSize );  /* Enforced by btreeInitPage() */
-    heap[0] = 0;
     btreeHeapInsert(heap, contentOffset-1);
     /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
     ** number of cells on the page. */
@@ -9167,10 +9160,9 @@ static int checkTreePage(
           cnt, data[hdr+7], iPage);
     }
   }
-  sqlite3PageFree(heap);
-  releasePage(pPage);
 
 end_of_check:
+  releasePage(pPage);
   pCheck->zPfx = saved_zPfx;
   pCheck->v1 = saved_v1;
   pCheck->v2 = saved_v2;
@@ -9200,14 +9192,14 @@ char *sqlite3BtreeIntegrityCheck(
   int *pnErr    /* Write number of errors seen to this variable */
 ){
   Pgno i;
-  int nRef;
+  VVA_ONLY( int nRef );
   IntegrityCk sCheck;
   BtShared *pBt = p->pBt;
   char zErr[100];
 
   sqlite3BtreeEnter(p);
   assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE );
-  nRef = sqlite3PagerRefcount(pBt->pPager);
+  assert( (nRef = sqlite3PagerRefcount(pBt->pPager))>=0 );
   sCheck.pBt = pBt;
   sCheck.pPager = pBt->pPager;
   sCheck.nPage = btreePagecount(sCheck.pBt);
@@ -9217,21 +9209,26 @@ char *sqlite3BtreeIntegrityCheck(
   sCheck.zPfx = 0;
   sCheck.v1 = 0;
   sCheck.v2 = 0;
-  *pnErr = 0;
+  sCheck.aPgRef = 0;
+  sCheck.heap = 0;
+  sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
   if( sCheck.nPage==0 ){
-    sqlite3BtreeLeave(p);
-    return 0;
+    goto integrity_ck_cleanup;
   }
 
   sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1);
   if( !sCheck.aPgRef ){
-    *pnErr = 1;
-    sqlite3BtreeLeave(p);
-    return 0;
+    sCheck.mallocFailed = 1;
+    goto integrity_ck_cleanup;
+  }
+  sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize );
+  if( sCheck.heap==0 ){
+    sCheck.mallocFailed = 1;
+    goto integrity_ck_cleanup;
   }
+
   i = PENDING_BYTE_PAGE(pBt);
   if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);
-  sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
 
   /* Check the integrity of the freelist
   */
@@ -9249,9 +9246,7 @@ char *sqlite3BtreeIntegrityCheck(
       checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0);
     }
 #endif
-    sCheck.zPfx = "List of tree roots: ";
     checkTreePage(&sCheck, aRoot[i], NULL, NULL);
-    sCheck.zPfx = 0;
   }
 
   /* Make sure every page in the file is referenced
@@ -9276,28 +9271,20 @@ char *sqlite3BtreeIntegrityCheck(
 #endif
   }
 
-  /* Make sure this analysis did not leave any unref() pages.
-  ** This is an internal consistency check; an integrity check
-  ** of the integrity check.
-  */
-  if( NEVER(nRef != sqlite3PagerRefcount(pBt->pPager)) ){
-    checkAppendMsg(&sCheck,
-      "Outstanding page count goes from %d to %d during this analysis",
-      nRef, sqlite3PagerRefcount(pBt->pPager)
-    );
-  }
-
   /* Clean  up and report errors.
   */
-  sqlite3BtreeLeave(p);
+integrity_ck_cleanup:
+  sqlite3PageFree(sCheck.heap);
   sqlite3_free(sCheck.aPgRef);
   if( sCheck.mallocFailed ){
     sqlite3StrAccumReset(&sCheck.errMsg);
-    *pnErr = sCheck.nErr+1;
-    return 0;
+    sCheck.nErr++;
   }
   *pnErr = sCheck.nErr;
   if( sCheck.nErr==0 ) sqlite3StrAccumReset(&sCheck.errMsg);
+  /* Make sure this analysis did not leave any unref() pages. */
+  assert( nRef==sqlite3PagerRefcount(pBt->pPager) );
+  sqlite3BtreeLeave(p);
   return sqlite3StrAccumFinish(&sCheck.errMsg);
 }
 #endif /* SQLITE_OMIT_INTEGRITY_CHECK */
index d74ea5557f719e26a7cc4307db4733ffcf46f63e..cbf6c998479e427d5247504c3047b5962e93bca4 100644 (file)
@@ -682,6 +682,7 @@ struct IntegrityCk {
   const char *zPfx; /* Error message prefix */
   int v1, v2;       /* Values for up to two %d fields in zPfx */
   StrAccum errMsg;  /* Accumulate the error message text here */
+  u32 *heap;        /* Min-heap used for analyzing cell coverage */
 };
 
 /*
index 982413ca8a698dfd2497e02467f8fe928649fb8c..060edb8d1dd7755b30cacdc5a090dbc03fcb66c7 100644 (file)
@@ -6387,12 +6387,14 @@ u8 sqlite3PagerIsreadonly(Pager *pPager){
   return pPager->readOnly;
 }
 
+#ifdef SQLITE_DEBUG
 /*
 ** Return the number of references to the pager.
 */
 int sqlite3PagerRefcount(Pager *pPager){
   return sqlite3PcacheRefCount(pPager->pPCache);
 }
+#endif
 
 /*
 ** Return the approximate number of bytes of memory currently
index e07fa88fc5fe6cfcc7ff525a1dec6ef085e4c0a3..e3b57f435e1ea0af92ca6156487ba5b4c47f4b32 100644 (file)
@@ -173,7 +173,9 @@ int sqlite3PagerSharedLock(Pager *pPager);
 /* Functions used to query pager state and configuration. */
 u8 sqlite3PagerIsreadonly(Pager*);
 u32 sqlite3PagerDataVersion(Pager*);
-int sqlite3PagerRefcount(Pager*);
+#ifdef SQLITE_DEBUG
+  int sqlite3PagerRefcount(Pager*);
+#endif
 int sqlite3PagerMemUsed(Pager*);
 const char *sqlite3PagerFilename(Pager*, int);
 const sqlite3_vfs *sqlite3PagerVfs(Pager*);