]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Improved error messages from PRAGMA integrity_check. Identify the root of
authordrh <>
Sat, 1 Apr 2023 13:14:53 +0000 (13:14 +0000)
committerdrh <>
Sat, 1 Apr 2023 13:14:53 +0000 (13:14 +0000)
the tree when a problem is found in a b-tree, making it easier to track the
problem to a specific table or index.

FossilOrigin-Name: a1cb152e69c7c6cdd99300c91a8104716089de459d9d19e33ef38432aad70908

manifest
manifest.uuid
src/btree.c
src/btreeInt.h
test/corrupt2.test
test/corrupt3.test
test/corrupt7.test
test/corruptC.test
test/corruptD.test
test/pragma.test

index 589edfc74eab86a06f209d88bca13a459d4b3648..4e72d9d151b7d77d611334e722f011748ac8f84d 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C In\sthe\sb-tree\smodule\suse\s%u\sinstead\sof\s%d\sto\sprint\sunsigned\squantities\ssuch\nas\spage\snumbers\sand\soffsets.
-D 2023-04-01T12:22:57.449
+C Improved\serror\smessages\sfrom\sPRAGMA\sintegrity_check.\s\sIdentify\sthe\sroot\sof\nthe\stree\swhen\sa\sproblem\sis\sfound\sin\sa\sb-tree,\smaking\sit\seasier\sto\strack\sthe\nproblem\sto\sa\sspecific\stable\sor\sindex.
+D 2023-04-01T13:14:53.367
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -564,9 +564,9 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf
 F src/backup.c a2891172438e385fdbe97c11c9745676bec54f518d4447090af97189fd8e52d7
 F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d
 F src/btmutex.c 6ffb0a22c19e2f9110be0964d0731d2ef1c67b5f7fabfbaeb7b9dabc4b7740ca
-F src/btree.c 0fda1fc90c2b240df720c020276e3027e0aa77313dbc667341ba27597557b4d8
+F src/btree.c ecce2a6cf75ccd1f419f774a026ab102399aeae90f33abb14aed363c4e0f839c
 F src/btree.h aa354b9bad4120af71e214666b35132712b8f2ec11869cb2315c52c81fad45cc
-F src/btreeInt.h 06bb2c1a07172d5a1cd27a2a5d617b93b1e976c5873709c31964786f86365a6e
+F src/btreeInt.h a3268a60cbc91f578001f44ba40aae9c1b8aecbb0d2c095dd7fc54b0872ea4b8
 F src/build.c 8357d6ca9a8c9afc297c431df28bc2af407b47f3ef2311875276c944b30c4d54
 F src/callback.c 4cd7225b26a97f7de5fee5ae10464bed5a78f2adefe19534cc2095b3a8ca484a
 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
@@ -872,18 +872,18 @@ F test/conflict2.test 5557909ce683b1073982f5d1b61dfb1d41e369533bfdaf003180c5bc87
 F test/conflict3.test 81865d9599609aca394fb3b9cd5f561d4729ea5b176bece3644f6ecb540f88ac
 F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4
 F test/corrupt.test d7cb0300e4a297147b6a05e92a1684bc8973635c3bcaa3d66e983c9cbdbf47a3
-F test/corrupt2.test bb50042cf9a1f1023d73af325d47eb02a6bb11e3c52f8812644b220c5d4bca35
-F test/corrupt3.test 2520432b1fbf99994841e69804a3c59fb828183f4d09b85a1631bc7adca17e31
+F test/corrupt2.test 6e0c1e1c2ff4bedde4bc73f16250d74ae5b3d9ece086640ce88b9a94620ba993
+F test/corrupt3.test 6a982535d52c8165654cbc79a043cfd0bf02495a5efbf4754295e056fc548539
 F test/corrupt4.test b5ae41607e8d17d9c1f3e94fdb572ce061ed3beeebdb46fb3a348181b8c8a097
 F test/corrupt5.test 387be3250795e2a86e6234745558b80efb248a357d0cd8e53bce75c7463f545d
 F test/corrupt6.test fc6a891716139665dae0073b6945e3670bf92568
-F test/corrupt7.test b036f94bda4b0b23a2919bf717046ce9ecca4543
+F test/corrupt7.test ffa86896fe63a3d00b0a131e1e64f402e4da9f7e5d89609d6501c851e511d73a
 F test/corrupt8.test 2399dfe40d2c0c63af86706e30f3e6302a8d0516
 F test/corrupt9.test 730a3db08d4ab9aa43392ea30d9c2b4879cbff85
 F test/corruptA.test 112f4b2ae0b95ebf3ea63718642fb969a93acea557ace3a307234d19c245989b
 F test/corruptB.test 73a8d6c0b9833697ecf16b63e3c5c05c945b5dec
-F test/corruptC.test 74d4498fd25759618b393f1e9cde111de828b88c1848ab320f6c179fd52b5a60
-F test/corruptD.test 33a37ce3ed56a20093ceee778cd2d7109c7085a59f3213d2baede11d952e8e50
+F test/corruptC.test 9cf32275dae3ca33f645afe5d1d3f5ba5ac2af2b0833dfb5282f9dccb6fb81bb
+F test/corruptD.test a828c788535946a372a56a750b242cd96287cd823657abe5a73c5e51b91bdd28
 F test/corruptE.test 4143791f2dfb443aec5b7fabfa5821e6063eccc3b49b06f212c2f014715fd476
 F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
 F test/corruptG.test adf79b669cbfd19e28c8191a610d083ae53a6d51
@@ -1380,7 +1380,7 @@ F test/pendingrace.test cbdf0f74bc939fb43cebad64dda7a0b5a3941a10b7e9cc2b596ff3e4
 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
 F test/permutations.test 8bd6b6db541e2a7f9bb894be99ef5c00526b23762c4a00c574e1cba697495125
 F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
-F test/pragma.test d21ae02249f2a1813f016efebe616a1916b3f9abd71867da6211a50bfea373ba
+F test/pragma.test 57a36226218c03cfb381019fe43234b2cefbd8a1f12825514f906a17ccf7991e
 F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
 F test/pragma3.test 92a46bbea12322dd94a404f49edcfbfc913a2c98115f0d030a7459bb4712ef31
 F test/pragma4.test ca5e4dfc46adfe490f75d73734f70349d95a199e6510973899e502eef2c8b1f8
@@ -2052,8 +2052,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P babe2b5e59647ac9db4601e67c25190aac14eb76d5fcb9fa5b3692b955fefd61
-R 48deb435a759e04a65c214c6987fb0c1
+P 33ac62d8eec56eb71f20ccd28a5d6e4e8051522feb2db0199abee9e18ce1f64e
+R 46b4ea5505ae8daa6bae8608979d5af1
 U drh
-Z 5e57bd2f4f9c8a5c6b6db368295f00fa
+Z d031925974df47c7e88e1b1118ce617e
 # Remove this line to create a well-formed Fossil manifest.
index e915d72023287667f945c6149d3588ac89717229..5e1238dd89e90404b82894cab58105f717e0f938 100644 (file)
@@ -1 +1 @@
-33ac62d8eec56eb71f20ccd28a5d6e4e8051522feb2db0199abee9e18ce1f64e
\ No newline at end of file
+a1cb152e69c7c6cdd99300c91a8104716089de459d9d19e33ef38432aad70908
\ No newline at end of file
index ec0fc07ac511b352dfaca3806cb661da4580afab..1b91120ffde3ce3a715010a99529635cb343389f 100644 (file)
@@ -10283,7 +10283,8 @@ static void checkAppendMsg(
     sqlite3_str_append(&pCheck->errMsg, "\n", 1);
   }
   if( pCheck->zPfx ){
-    sqlite3_str_appendf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2);
+    sqlite3_str_appendf(&pCheck->errMsg, pCheck->zPfx,
+                        pCheck->v0, pCheck->v1, pCheck->v2);
   }
   sqlite3_str_vappendf(&pCheck->errMsg, zFormat, ap);
   va_end(ap);
@@ -10544,8 +10545,8 @@ static int checkTreePage(
   usableSize = pBt->usableSize;
   if( iPage==0 ) return 0;
   if( checkRef(pCheck, iPage) ) return 0;
-  pCheck->zPfx = "Page %u: ";
-  pCheck->v1 = iPage;
+  pCheck->zPfx = "Tree %u page %u: ";
+  pCheck->v0 = pCheck->v1 = iPage;
   if( (rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0 ){
     checkAppendMsg(pCheck,
        "unable to get the page. error code=%d", rc);
@@ -10571,7 +10572,7 @@ static int checkTreePage(
   hdr = pPage->hdrOffset;
 
   /* Set up for cell analysis */
-  pCheck->zPfx = "On tree page %u cell %u: ";
+  pCheck->zPfx = "Tree %u page %u cell %u: ";
   contentOffset = get2byteNotZero(&data[hdr+5]);
   assert( contentOffset<=usableSize );  /* Enforced by btreeInitPage() */
 
@@ -10591,7 +10592,7 @@ static int checkTreePage(
     pgno = get4byte(&data[hdr+8]);
 #ifndef SQLITE_OMIT_AUTOVACUUM
     if( pBt->autoVacuum ){
-      pCheck->zPfx = "On page %u at right child: ";
+      pCheck->zPfx = "Tree %u page %u right child: ";
       checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage);
     }
 #endif
@@ -10844,7 +10845,7 @@ int sqlite3BtreeIntegrityCheck(
   /* Check the integrity of the freelist
   */
   if( bCkFreelist ){
-    sCheck.zPfx = "Main freelist: ";
+    sCheck.zPfx = "Freelist: ";
     checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]),
               get4byte(&pBt->pPage1->aData[36]));
     sCheck.zPfx = 0;
@@ -10892,7 +10893,7 @@ int sqlite3BtreeIntegrityCheck(
     for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){
 #ifdef SQLITE_OMIT_AUTOVACUUM
       if( getPageReferenced(&sCheck, i)==0 ){
-        checkAppendMsg(&sCheck, "Page %u is never used", i);
+        checkAppendMsg(&sCheck, "Page %u: never used", i);
       }
 #else
       /* If the database supports auto-vacuum, make sure no tables contain
@@ -10900,11 +10901,11 @@ int sqlite3BtreeIntegrityCheck(
       */
       if( getPageReferenced(&sCheck, i)==0 && 
          (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){
-        checkAppendMsg(&sCheck, "Page %u is never used", i);
+        checkAppendMsg(&sCheck, "Page %u: never used", i);
       }
       if( getPageReferenced(&sCheck, i)!=0 && 
          (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){
-        checkAppendMsg(&sCheck, "Pointer map page %u is referenced", i);
+        checkAppendMsg(&sCheck, "Page %u: pointer map referenced", i);
       }
 #endif
     }
index 79c3296d046dc6f2c2d8fb93d7c412e6e7ae3c96..160a6af18f543c9b88f424851a94be332bad1c26 100644 (file)
@@ -701,8 +701,9 @@ struct IntegrityCk {
   int rc;           /* SQLITE_OK, SQLITE_NOMEM, or SQLITE_INTERRUPT */
   u32 nStep;        /* Number of steps into the integrity_check process */
   const char *zPfx; /* Error message prefix */
-  Pgno v1;          /* Value for first %u substitution in zPfx */
-  int v2;           /* Value for second %d substitution in zPfx */
+  Pgno v0;          /* Value for first %u substitution in zPfx (root page) */
+  Pgno v1;          /* Value for second %u substitution in zPfx (current pg) */
+  int v2;           /* Value for third %d substitution in zPfx */
   StrAccum errMsg;  /* Accumulate the error message text here */
   u32 *heap;        /* Min-heap used for analyzing cell coverage */
   sqlite3 *db;      /* Database connection running the check */
index f97a526ef5762fd9a191f23346381f5f21e98f4e..96d28490aa5a918c06f1ef84dd153946a9354a5a 100644 (file)
@@ -99,7 +99,7 @@ do_test corrupt2-1.4 {
   # of MemPage.nFree 
   catchsql {PRAGMA quick_check} db2
 } {0 {{*** in database main ***
-Page 1: free space corruption}}}
+Tree 1 page 1: free space corruption}}}
 
 do_test corrupt2-1.5 {
   db2 close
@@ -120,7 +120,7 @@ do_test corrupt2-1.5 {
   sqlite3 db2 corrupt.db
   catchsql {PRAGMA quick_check} db2
 } {0 {{*** in database main ***
-Page 1: free space corruption}}}
+Tree 1 page 1: free space corruption}}}
 db2 close
 
 # Corrupt a database by having 2 indices of the same name:
@@ -248,8 +248,8 @@ do_test corrupt2-5.1 {
   }
   set result
 } {{*** in database main ***
-On tree page 2 cell 0: 2nd reference to page 10
-Page 4 is never used}}
+Tree 11 page 2 cell 0: 2nd reference to page 10
+Page 4: never used}}
 
 db2 close
 
@@ -591,7 +591,7 @@ do_test 14.2 {
 do_execsql_test 14.3 {
   PRAGMA integrity_check;
 } {{*** in database main ***
-Main freelist: size is 3 but should be 2}}
+Freelist: size is 3 but should be 2}}
 
 # Use 2 of the free pages on the free-list.
 #
@@ -603,7 +603,7 @@ do_execsql_test 14.4 {
 do_execsql_test 14.5 {
   PRAGMA integrity_check;
 } {{*** in database main ***
-Main freelist: size is 1 but should be 0}}
+Freelist: size is 1 but should be 0}}
 
 
 finish_test
index 7a2e174ead2992bf4b3e37e19e91cfd2f7900c28..691302f7af5dc87d1e3a5de4d001a89abbb3101a 100644 (file)
@@ -82,7 +82,7 @@ do_test corrupt3-1.8 {
     PRAGMA integrity_check
   }
 } {0 {{*** in database main ***
-On tree page 2 cell 0: 2nd reference to page 3}}}
+Tree 2 page 2 cell 0: 2nd reference to page 3}}}
 
 # Change the pointer for the first page of the overflow
 # change to be a non-existant page.
@@ -100,8 +100,8 @@ do_test corrupt3-1.10 {
     PRAGMA integrity_check
   }
 } {0 {{*** in database main ***
-On tree page 2 cell 0: invalid page number 4
-Page 3 is never used}}}
+Tree 2 page 2 cell 0: invalid page number 4
+Page 3: never used}}}
 do_test corrupt3-1.11 {
   db close
   hexio_write test.db 2044 [hexio_render_int32 0]
@@ -115,7 +115,7 @@ do_test corrupt3-1.12 {
     PRAGMA integrity_check
   }
 } {0 {{*** in database main ***
-On tree page 2 cell 0: overflow list length is 0 but should be 1
-Page 3 is never used}}}
+Tree 2 page 2 cell 0: overflow list length is 0 but should be 1
+Page 3: never used}}}
 
 finish_test
index aa66cc7ece6334e72b4655b710a66c5b04b717f8..b62515b7847b0b94a7ae49ba5f6541976a9c2aa0 100644 (file)
@@ -70,14 +70,14 @@ do_test corrupt7-2.1 {
   sqlite3 db test.db
   db eval {PRAGMA integrity_check(1)}
 } {{*** in database main ***
-On tree page 2 cell 15: Offset 65457 out of range 945..1020}}
+Tree 2 page 2 cell 15: Offset 65457 out of range 945..1020}}
 do_test corrupt7-2.2 {
   db close
   hexio_write test.db 1062 04
   sqlite3 db test.db
   db eval {PRAGMA integrity_check(1)}
 } {{*** in database main ***
-On tree page 2 cell 15: Offset 1201 out of range 945..1020}}
+Tree 2 page 2 cell 15: Offset 1201 out of range 945..1020}}
   
 # The code path that was causing the buffer overrun that this test
 # case was checking for was removed.
index a56abeec7282d0acd205e83254458027c8cc9a2c..f5733a818616440fe608c70ee38613d1c0c1386d 100644 (file)
@@ -98,7 +98,7 @@ do_test corruptC-2.1 {
   sqlite3 db test.db
   catchsql {PRAGMA integrity_check}
 } {0 {{*** in database main ***
-Page 3: free space corruption}}}
+Tree 3 page 3: free space corruption}}}
 
 # test that a corrupt content offset size is handled (seed 5649)
 #
@@ -165,7 +165,7 @@ do_test corruptC-2.5 {
   catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;}
   catchsql {PRAGMA integrity_check}
 } {0 {{*** in database main ***
-On tree page 4 cell 19: Extends off end of page} {database disk image is malformed}}}
+Tree 4 page 4 cell 19: Extends off end of page} {database disk image is malformed}}}
 
 # {0 {{*** in database main ***
 # Corruption detected in cell 710 on page 4
index eb6ccb3fcd29358380022d4e39adeb159dfb7082..c35388adfb085dbb7976b6187a8da4520b31defb 100644 (file)
@@ -113,7 +113,7 @@ do_test corruptD-1.1.1 {
   hexio_write test.db [expr 1024+1] FFFF
   catchsql { PRAGMA quick_check }
 } {0 {{*** in database main ***
-Page 2: free space corruption}}}
+Tree 2 page 2: free space corruption}}}
 do_test corruptD-1.1.2 {
   incr_change_counter
   hexio_write test.db [expr 1024+1] [hexio_render_int32 1021]
index a3e1d3cd65eafbc53fab59a7a8b8fb7bd8f7c64d..5b45a74400cee03b8904e0b88673638859ac3fe7 100644 (file)
@@ -433,9 +433,9 @@ ifcapable attach {
         PRAGMA integrity_check
       }
     } {{*** in database t2 ***
-Page 4 is never used
-Page 5 is never used
-Page 6 is never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}}
+Page 4: never used
+Page 5: never used
+Page 6: never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}}
     do_execsql_test pragma-3.9b {
       PRAGMA t2.integrity_check=t2;
     } {{row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}}
@@ -447,79 +447,79 @@ Page 6 is never used} {row 1 missing from index i2} {row 2 missing from index i2
         PRAGMA integrity_check=1
       }
     } {{*** in database t2 ***
-Page 4 is never used}}
+Page 4: never used}}
     do_test pragma-3.11 {
       execsql {
         PRAGMA integrity_check=5
       }
     } {{*** in database t2 ***
-Page 4 is never used
-Page 5 is never used
-Page 6 is never used} {row 1 missing from index i2} {row 2 missing from index i2}}
+Page 4: never used
+Page 5: never used
+Page 6: never used} {row 1 missing from index i2} {row 2 missing from index i2}}
     do_test pragma-3.12 {
       execsql {
         PRAGMA integrity_check=4
       }
     } {{*** in database t2 ***
-Page 4 is never used
-Page 5 is never used
-Page 6 is never used} {row 1 missing from index i2}}
+Page 4: never used
+Page 5: never used
+Page 6: never used} {row 1 missing from index i2}}
     do_test pragma-3.13 {
       execsql {
         PRAGMA integrity_check=3
       }
     } {{*** in database t2 ***
-Page 4 is never used
-Page 5 is never used
-Page 6 is never used}}
+Page 4: never used
+Page 5: never used
+Page 6: never used}}
     do_test pragma-3.14 {
       execsql {
         PRAGMA integrity_check(2)
       }
     } {{*** in database t2 ***
-Page 4 is never used
-Page 5 is never used}}
+Page 4: never used
+Page 5: never used}}
     do_test pragma-3.15 {
       execsql {
         ATTACH 'testerr.db' AS t3;
         PRAGMA integrity_check
       }
     } {{*** in database t2 ***
-Page 4 is never used
-Page 5 is never used
-Page 6 is never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {*** in database t3 ***
-Page 4 is never used
-Page 5 is never used
-Page 6 is never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}}
+Page 4: never used
+Page 5: never used
+Page 6: never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {*** in database t3 ***
+Page 4: never used
+Page 5: never used
+Page 6: never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}}
     do_test pragma-3.16 {
       execsql {
         PRAGMA integrity_check(10)
       }
     } {{*** in database t2 ***
-Page 4 is never used
-Page 5 is never used
-Page 6 is never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {*** in database t3 ***
-Page 4 is never used
-Page 5 is never used
-Page 6 is never used} {row 1 missing from index i2}}
+Page 4: never used
+Page 5: never used
+Page 6: never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {*** in database t3 ***
+Page 4: never used
+Page 5: never used
+Page 6: never used} {row 1 missing from index i2}}
     do_test pragma-3.17 {
       execsql {
         PRAGMA integrity_check=8
       }
     } {{*** in database t2 ***
-Page 4 is never used
-Page 5 is never used
-Page 6 is never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {*** in database t3 ***
-Page 4 is never used
-Page 5 is never used}}
+Page 4: never used
+Page 5: never used
+Page 6: never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {*** in database t3 ***
+Page 4: never used
+Page 5: never used}}
     do_test pragma-3.18 {
       execsql {
         PRAGMA integrity_check=4
       }
     } {{*** in database t2 ***
-Page 4 is never used
-Page 5 is never used
-Page 6 is never used} {row 1 missing from index i2}}
+Page 4: never used
+Page 5: never used
+Page 6: never used} {row 1 missing from index i2}}
   }
   do_test pragma-3.19 {
     catch {db close}