]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the xIntegrity method to the sqlite3_module object. Implement this
authordrh <>
Wed, 6 Sep 2023 12:52:00 +0000 (12:52 +0000)
committerdrh <>
Wed, 6 Sep 2023 12:52:00 +0000 (12:52 +0000)
method in RTREE, FTS3/4, and FTS5 so that "PRAGMA integrity_check" also
verifies the correctness of shadow tables associated with those virtual
tables.

FossilOrigin-Name: 17bede8cdefd968210dd8a5a2617acbe12ba2c99fdd5e88c5def8665e7bec2d7

24 files changed:
ext/fts3/fts3.c
ext/fts5/fts5_main.c
ext/fts5/test/fts5aa.test
ext/fts5/test/fts5aux.test
ext/fts5/test/fts5content.test
ext/fts5/test/fts5contentless.test
ext/fts5/test/fts5contentless2.test
ext/fts5/test/fts5contentless3.test
ext/fts5/test/fts5contentless4.test
ext/fts5/test/fts5contentless5.test
ext/fts5/test/fts5corrupt.test
ext/fts5/test/fts5corrupt2.test
ext/rtree/rtree.c
ext/rtree/rtree_util.tcl
ext/rtree/rtreecheck.test
manifest
manifest.uuid
src/pragma.c
src/sqlite.h.in
src/vdbe.c
test/fts3conf.test
test/fts3corrupt4.test
test/fts4check.test
test/fts4langid.test

index 43a9daf60d0f9402f79ecf29fb7d6cad397d22e4..03013b0bf42c900369b344adcc91a12b16bada3d 100644 (file)
@@ -3980,8 +3980,32 @@ static int fts3ShadowName(const char *zName){
   return 0;
 }
 
+/*
+** Implementation of the xIntegrity() method on the FTS3/FTS4 virtual
+** table.
+*/
+static char *fts3Integrity(sqlite3_vtab *pVtab){
+  Fts3Table *p = (Fts3Table*)pVtab;
+  char *zSql;
+  int rc;
+  char *zErr = 0;
+
+  zSql = sqlite3_mprintf(
+            "INSERT INTO \"%w\".\"%w\"(\"%w\") VALUES('integrity-check');",
+            p->zDb, p->zName, p->zName);
+  rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
+  sqlite3_free(zSql);
+  if( rc ){
+    zErr = sqlite3_mprintf("malformed inverted index for FTS%d table %s.%s",
+              p->bFts4 ? 4 : 3, p->zDb, p->zName);
+  }
+  return zErr;
+}
+
+
+
 static const sqlite3_module fts3Module = {
-  /* iVersion      */ 3,
+  /* iVersion      */ 4,
   /* xCreate       */ fts3CreateMethod,
   /* xConnect      */ fts3ConnectMethod,
   /* xBestIndex    */ fts3BestIndexMethod,
@@ -4005,6 +4029,7 @@ static const sqlite3_module fts3Module = {
   /* xRelease      */ fts3ReleaseMethod,
   /* xRollbackTo   */ fts3RollbackToMethod,
   /* xShadowName   */ fts3ShadowName,
+  /* xIntegrity    */ fts3Integrity,
 };
 
 /*
index c34a5a332bf3adb7f8e84e3a602501b5693caa95..fac4dd06bcf841121060212df2a3cc2b6ba9c803 100644 (file)
@@ -2850,9 +2850,34 @@ static int fts5ShadowName(const char *zName){
   return 0;
 }
 
+/*
+** Run an integrity check on the FTS5 data structures.  Return a string
+** if anything is found amiss.  Return a NULL pointer if everything is
+** OK.
+*/
+static char *fts5Integrity(sqlite3_vtab *pVtab){
+  Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
+  Fts5Config *pConfig = pTab->p.pConfig;
+  char *zSql;
+  int rc;
+  char *zErr = 0;
+
+  zSql = sqlite3_mprintf(
+            "INSERT INTO \"%w\".\"%w\"(\"%w\") VALUES('integrity-check');",
+            pConfig->zDb, pConfig->zName, pConfig->zName);
+  rc = sqlite3_exec(pConfig->db, zSql, 0, 0, 0);
+  sqlite3_free(zSql);
+  if( rc ){
+    zErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s",
+              pConfig->zDb, pConfig->zName);
+  }
+  return zErr;
+
+}
+
 static int fts5Init(sqlite3 *db){
   static const sqlite3_module fts5Mod = {
-    /* iVersion      */ 3,
+    /* iVersion      */ 4,
     /* xCreate       */ fts5CreateMethod,
     /* xConnect      */ fts5ConnectMethod,
     /* xBestIndex    */ fts5BestIndexMethod,
@@ -2875,7 +2900,8 @@ static int fts5Init(sqlite3 *db){
     /* xSavepoint    */ fts5SavepointMethod,
     /* xRelease      */ fts5ReleaseMethod,
     /* xRollbackTo   */ fts5RollbackToMethod,
-    /* xShadowName   */ fts5ShadowName
+    /* xShadowName   */ fts5ShadowName,
+    /* xIntegrity    */ fts5Integrity
   };
 
   int rc;
index 59ce4f6a1fd5d549e25b0e7a6d34eb34fcea0a53..e1551fc51602d5617e552ad0881292de97792ad9 100644 (file)
@@ -65,7 +65,9 @@ foreach w {a b c d e f} {
 
 do_execsql_test 2.4 {
   INSERT INTO t1(t1) VALUES('integrity-check');
-}
+  PRAGMA integrity_check;
+  PRAGMA integrity_check(t1);
+} {ok ok}
 
 
 #-------------------------------------------------------------------------
@@ -88,6 +90,7 @@ foreach {i x y} {
 } {
   do_execsql_test 3.$i.1 { INSERT INTO t1 VALUES($x, $y) }
   do_execsql_test 3.$i.2 { INSERT INTO t1(t1) VALUES('integrity-check') }
+  do_execsql_test 3.$i.3 { PRAGMA integrity_check(t1) } ok
   if {[set_test_counter errors]} break
 }
 
@@ -135,7 +138,7 @@ foreach {i x y} {
    10 {ddd abcde dddd dd c} {dddd c c d abcde}
 } {
   do_execsql_test 5.$i.1 { INSERT INTO t1 VALUES($x, $y) }
-  do_execsql_test 5.$i.2 { INSERT INTO t1(t1) VALUES('integrity-check') }
+  do_execsql_test 5.$i.2 { PRAGMA integrity_check(t1) } ok
   if {[set_test_counter errors]} break
 }
 
index 561067c4bce0eb04e15a37918965248caf19ddfc..597c636f43a59a9efb74f3fd435ff3df63ecf0fb 100644 (file)
@@ -308,4 +308,3 @@ do_catchsql_test 10.1.4 {
 } {1 {unable to use function firstcol in the requested context}}
 
 finish_test
-
index 74a74e2ad02f35146761c5be53f3343c3531c169..ca2726a902c6ee354610c84d4cb5706e7ae699d9 100644 (file)
@@ -294,4 +294,3 @@ do_catchsql_test 7.2.5 {
 } {1 {recursively defined fts5 content table}}
 
 finish_test
-
index f75ccb44c2381999e4d6d8575a0d87f8693840b7..48cfd10ffa74ed5a8e99c08f26d69d24d926d258 100644 (file)
@@ -268,4 +268,3 @@ do_execsql_test 8.2 {
 } {}
 
 finish_test
-
index fbb857ab386ef54b528b2b4be35b9b6dc6dbb9ef..fdd7a60fce7e401d06c857b6a89967077a10d9ae 100644 (file)
@@ -205,4 +205,3 @@ foreach {tn step} {
 
 
 finish_test
-
index a44311e45aed0a53c29f172df29becad4de4e0db..76119dc59291753668b7f92f20539ab9b5cabe09 100644 (file)
@@ -193,4 +193,3 @@ do_execsql_test 3.7 {
 
 
 finish_test
-
index 1c2666dcf85fe57b01298c0f358d1d05040af538..702b33a9de87be1147ead3cf781bcd762d591d11 100644 (file)
@@ -245,4 +245,3 @@ do_execsql_test 4.3 {
 }
 
 finish_test
-
index 1541b0c68daa45f22a8d8618ba2d9d7d0fa7d71d..a20134d1e7209524c4b47429e36624045ec94fb9 100644 (file)
@@ -56,4 +56,3 @@ foreach {tn up err} {
 }
 
 finish_test
-
index 5f13513ec724dc250922a60b736a503e6077ec11..9aa84a0ef23d068cd408f22c277f77fb0072cefe 100644 (file)
@@ -48,6 +48,10 @@ do_test 1.3 {
   }
   catchsql { INSERT INTO t1(t1) VALUES('integrity-check') }
 } {1 {database disk image is malformed}}
+do_execsql_test 1.3b {
+  PRAGMA integrity_check(t1);
+} {{malformed inverted index for FTS5 table main.t1}}
+
 
 do_test 1.4 {
   db_restore_and_reopen
index a815320b763fb8eb3d218aeff0d83181808e15a2..06e2e74258276e6d3ffa2a24cf262924b9a26f0e 100644 (file)
@@ -167,6 +167,9 @@ foreach {tn hdr} {
       do_test 3.$tn.$tn2.2 {
         catchsql { INSERT INTO x3(x3) VALUES('integrity-check') }
       } {1 {database disk image is malformed}}
+      do_execsql_test 3.$tn.$tn2.3 {
+        PRAGMA integrity_check(x3);
+      } {{malformed inverted index for FTS5 table main.x3}}
     }
 
     execsql ROLLBACK
index adf73e41db180fbd820c8693d26b403908bc3f5a..5fb0deca3ea50ce5dc48ad6f47fc62d6888a2ec1 100644 (file)
@@ -3502,8 +3502,11 @@ static int rtreeShadowName(const char *zName){
   return 0;
 }
 
+/* Forward declaration */
+static char *rtreeIntegrity(sqlite3_vtab*);
+
 static sqlite3_module rtreeModule = {
-  3,                          /* iVersion */
+  4,                          /* iVersion */
   rtreeCreate,                /* xCreate - create a table */
   rtreeConnect,               /* xConnect - connect to an existing table */
   rtreeBestIndex,             /* xBestIndex - Determine search strategy */
@@ -3526,7 +3529,8 @@ static sqlite3_module rtreeModule = {
   rtreeSavepoint,             /* xSavepoint */
   0,                          /* xRelease */
   0,                          /* xRollbackTo */
-  rtreeShadowName             /* xShadowName */
+  rtreeShadowName,            /* xShadowName */
+  rtreeIntegrity              /* xIntegrity */
 };
 
 static int rtreeSqlInit(
@@ -4360,6 +4364,26 @@ static int rtreeCheckTable(
   return check.rc;
 }
 
+/*
+** Implementation of the xIntegrity method for Rtree.
+*/
+static char *rtreeIntegrity(sqlite3_vtab *pVtab){
+  Rtree *pRtree = (Rtree*)pVtab;
+  char *zErr = 0;
+  int rc;
+
+  rc = rtreeCheckTable(pRtree->db, pRtree->zDb, pRtree->zName, &zErr);
+  if( rc ){
+    sqlite3_free(zErr);
+    zErr = sqlite3_mprintf("error code %d while checking RTree %s.%s",
+                rc, pRtree->zDb, pRtree->zName);
+  }else if( zErr ){
+    zErr = sqlite3_mprintf("In RTree %s.%s:\n%z",
+                pRtree->zDb, pRtree->zName, zErr);
+  }
+  return zErr;
+}
+
 /*
 ** Usage:
 **
index afa588e4e9af3edd307c3f6a51dc7183caf1e8ec..5640baf4e075cc76d91f82380065b7e1aba894dc 100644 (file)
@@ -192,6 +192,6 @@ proc rtree_treedump {db zTab} {
 }
 
 proc do_rtree_integrity_test {tn tbl} {
-  uplevel [list do_execsql_test $tn "SELECT rtreecheck('$tbl')" ok]
+  uplevel [list do_execsql_test $tn.1 "SELECT rtreecheck('$tbl')" ok]
+  uplevel [list do_execsql_test $tn.2 "PRAGMA integrity_check" ok]
 }
-
index ff5397e1e15795400d22cf419bb03d5a1b23a082..7a98f9bf4e5a6eab83b23d4fb8799c0552b99618 100644 (file)
@@ -78,6 +78,11 @@ do_execsql_test 2.3 {
   SELECT rtreecheck('r1') 
 } {{Dimension 0 of cell 0 on node 1 is corrupt
 Dimension 1 of cell 3 on node 1 is corrupt}}
+do_execsql_test 2.3b { 
+  PRAGMA integrity_check;
+} {{In RTree main.r1:
+Dimension 0 of cell 0 on node 1 is corrupt
+Dimension 1 of cell 3 on node 1 is corrupt}}
 
 setup_simple_db
 do_execsql_test 2.4 {
@@ -85,12 +90,21 @@ do_execsql_test 2.4 {
   SELECT rtreecheck('r1') 
 } {{Mapping (3 -> 1) missing from %_rowid table
 Wrong number of entries in %_rowid table - expected 5, actual 4}}
+do_execsql_test 2.4b {
+  PRAGMA integrity_check
+} {{In RTree main.r1:
+Mapping (3 -> 1) missing from %_rowid table
+Wrong number of entries in %_rowid table - expected 5, actual 4}}
 
 setup_simple_db
 do_execsql_test 2.5 {
   UPDATE r1_rowid SET nodeno=2 WHERE rowid=3;
   SELECT rtreecheck('r1') 
 } {{Found (3 -> 2) in %_rowid table, expected (3 -> 1)}}
+do_execsql_test 2.5b {
+  PRAGMA integrity_check
+} {{In RTree main.r1:
+Found (3 -> 2) in %_rowid table, expected (3 -> 1)}}
 
 reset_db
 do_execsql_test 3.0 { 
@@ -104,14 +118,16 @@ do_execsql_test 3.0 {
   INSERT INTO r1 VALUES(7, 5, 0x00000080);
   INSERT INTO r1 VALUES(8, 5, 0x40490fdb);
   INSERT INTO r1 VALUES(9, 0x7f800000, 0x7f900000);
-  SELECT rtreecheck('r1') 
-} {ok}
+  SELECT rtreecheck('r1');
+  PRAGMA integrity_check;
+} {ok ok}
 
 do_execsql_test 3.1 { 
   CREATE VIRTUAL TABLE r2 USING rtree_i32(id, x1, x2);
   INSERT INTO r2 VALUES(2, -1*(1<<31), -1*(1<<31)+5);
-  SELECT rtreecheck('r2') 
-} {ok}
+  SELECT rtreecheck('r2');
+  PRAGMA integrity_check;
+} {ok ok}
 
 sqlite3_db_config db DEFENSIVE 0
 do_execsql_test 3.2 {
@@ -125,6 +141,11 @@ do_execsql_test 3.3 {
   UPDATE r2_node SET data = X'00001234';
   SELECT rtreecheck('r2')!='ok';
 } {1}
+do_execsql_test 3.4 {
+  PRAGMA integrity_check;
+} {{In RTree main.r2:
+Node 1 is too small for cell count of 4660 (4 bytes)
+Wrong number of entries in %_rowid table - expected 0, actual 1}}
 
 do_execsql_test 4.0 {
   CREATE TABLE notanrtree(i);
@@ -181,4 +202,3 @@ if {[permutation]=="inmemory_journal"} {
 }
 
 finish_test
-
index 24fefe807a4b0467698e08a6adf6901f84be40ee..15141baad77a73cd989ad373bfc09387bdac3197 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\sfew\sSQLITE_MISUSE\sreturns\sso\sthat\sthey\scall\ssqlite3MisuseError().
-D 2023-09-05T15:03:23.029
+C Add\sthe\sxIntegrity\smethod\sto\sthe\ssqlite3_module\sobject.\s\sImplement\sthis\nmethod\sin\sRTREE,\sFTS3/4,\sand\sFTS5\sso\sthat\s"PRAGMA\sintegrity_check"\salso\nverifies\sthe\scorrectness\sof\sshadow\stables\sassociated\swith\sthose\svirtual\ntables.
+D 2023-09-06T12:52:00.208
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -60,7 +60,7 @@ F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c
 F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
 F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d
 F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
-F ext/fts3/fts3.c 66d2ced306ac88c39c00d81184f2c60f338696af6ae8cc26ed7c361b157b09f7
+F ext/fts3/fts3.c 3393dcffc28bcef63d13f3d3cdcc71c3e23d2a9017687d701b9b4b1272ff2d51
 F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
 F ext/fts3/fts3Int.h e573c6d881f7238d77cc3fd2396cbb9b2fe13efef7d2ad295a155151c4e7efbd
 F ext/fts3/fts3_aux.c f0dc9bd98582615b7750218899bd0c729879b6bbf94d1be57ca1833ff49afc6f
@@ -95,7 +95,7 @@ F ext/fts5/fts5_config.c 054359543566cbff1ba65a188330660a5457299513ac71c53b3a07d
 F ext/fts5/fts5_expr.c bd3b81ce669c4104e34ffe66570af1999a317b142c15fccb112de9fb0caa57a6
 F ext/fts5/fts5_hash.c 65e7707bc8774706574346d18c20218facf87de3599b995963c3e6d6809f203d
 F ext/fts5/fts5_index.c 47c290589fa38f6a1860b4fc26716ed30d79ddc283b38813d1c8c1d702108ab8
-F ext/fts5/fts5_main.c 7070031993ba5b5d89b13206ec4ef624895f2f7c0ec72725913d301e4d382445
+F ext/fts5/fts5_main.c a2169916037e3d77014d8a18d3ff9f81a2bec8a334ea8905f0e27dbc513fcec3
 F ext/fts5/fts5_storage.c 3c9b41fce41b6410f2e8f82eb035c6a29b2560483f773e6dc98cf3cb2e4ddbb5
 F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae
 F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
@@ -107,7 +107,7 @@ F ext/fts5/fts5_vocab.c 12138e84616b56218532e3e8feb1d3e0e7ae845e33408dbe911df520
 F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde256bb05
 F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
 F ext/fts5/test/fts5_common.tcl a9de9c2209cc4e7ae3c753e783504e67206c6c1467d08f209cd0c5923d3e8d8b
-F ext/fts5/test/fts5aa.test 5bd43427b7d08ce2e19c488a26534be450538b9232d4d5305049e8de236e9aa9
+F ext/fts5/test/fts5aa.test ba5158eba7d61359becdfca895ef471072c7bf7b20e5e60dcb4d024c8419c926
 F ext/fts5/test/fts5ab.test bd932720c748383277456b81f91bc00453de2174f9762cd05f95d0495dc50390
 F ext/fts5/test/fts5ac.test a7aa7e1fefc6e1918aa4d3111d5c44a09177168e962c5fd2cca9620de8a7ed6d
 F ext/fts5/test/fts5ad.test e8cf959dfcd57c8e46d6f5f25665686f3b6627130a9a981371dafdf6482790de
@@ -121,7 +121,7 @@ F ext/fts5/test/fts5ak.test f459a64c9d38698af72a7c657ab6349bca96150241dd69fcce75
 F ext/fts5/test/fts5al.test 00c4c1c6a1366b73aa48ce2068c634520867c3cf7f5d1676ebbb775ee1f35734
 F ext/fts5/test/fts5alter.test 5565f7e4605512b69171ac18ca84398603f9f6456dbe377beeca97e83cc242cd
 F ext/fts5/test/fts5auto.test 78989e6527ce69c9eddbef7392fea5c10b0010cd2b2ae68eec7bc869c471e691
-F ext/fts5/test/fts5aux.test ebf6f2ff7cb556e83f66991b7f12bff016d3c83d4eab36704b649dd6b1437318
+F ext/fts5/test/fts5aux.test 29f60f7a25d98f6c129bacff5bca81f3f4adb8b097a7a919b0540a8c94247b73
 F ext/fts5/test/fts5auxdata.test eacc97ff04892f1a5f3d4df5a73f8bcbc3955ea1d12c9f24137eb1fc079e7611
 F ext/fts5/test/fts5bigid.test 2860854c2561a57594192b00c33a29f91cb85e25f3d6c03b5c2b8f62708f39dd
 F ext/fts5/test/fts5bigpl.test 6466c89b38439f0aba26ac09e232a6b963f29b1cbe1304f6a664fe1e7a8f5fd3
@@ -133,14 +133,14 @@ F ext/fts5/test/fts5columnsize.test 45459ce4dd9fd853b6044cdc9674921bff89e3d840f3
 F ext/fts5/test/fts5config.test 60094712debc59286c59aef0e6cf511c37d866802776a825ce437d26afe0817f
 F ext/fts5/test/fts5conflict.test 655925678e630d3cdf145d18725a558971806416f453ac8410ca8c04d934238d
 F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c073e19b3ae9126b2f4
-F ext/fts5/test/fts5content.test 213506436fb2c87567b8e31f6d43ab30aab99354cec74ed679f22aad0cdbf283
-F ext/fts5/test/fts5contentless.test eb31159d62811b3a32fb1cfb36be20f9d9db75637c7fe6aa7f5c533db2d00576
-F ext/fts5/test/fts5contentless2.test 12c778d134a121b8bad000fbf3ae900d53226fee840ce36fe941b92737f1fda7
-F ext/fts5/test/fts5contentless3.test 487dce16b6677f68b44d7cbd158b9b7275d25e2c14d713f9188d9645bb699286
-F ext/fts5/test/fts5contentless4.test 0f43ededc2874f65d7da99b641a82239854d98d3fa43db729f284b723f23b69f
-F ext/fts5/test/fts5contentless5.test 216962d51376b62e4ff45e8db00aa3e1ab548cb36b7fd450633e73b2d678f88e
-F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe
-F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f
+F ext/fts5/test/fts5content.test 219a4e49386b9b197b9b7cadca97ea10ddff858ecd8b763a1cb8bb07575afc2a
+F ext/fts5/test/fts5contentless.test 1cd1237894eeff11feb1ff8180044eac0b17dde22c181f7a722f2dcbfdb3377c
+F ext/fts5/test/fts5contentless2.test 14c83bdacf8230f5f7ca74ecf2926b87d8a7cb788a69ce9937020428ac4fe192
+F ext/fts5/test/fts5contentless3.test 353d871c5ea08992aed3e2ebda0b1bdc35116cd24fe330fe7cf05be1e2b49fd7
+F ext/fts5/test/fts5contentless4.test dd33ead36b048c9447b81ec358bd4a27166c49ffaac65a54e95eabf59f338947
+F ext/fts5/test/fts5contentless5.test 96041cbf5ef781a68a5d0f0d18a88030c47a52b156b17876ed6ce36e80e27a7e
+F ext/fts5/test/fts5corrupt.test b6d4034b682bb3387bc44c510c71b3c67d4349e4df139490fc0b69e6a972b99f
+F ext/fts5/test/fts5corrupt2.test 99e7e23a58b4d89eb7167c6de1669cbc595cd3c79ab333e0eb56405473319e77
 F ext/fts5/test/fts5corrupt3.test 7da9895dafa404efd20728f66ff4b94399788bdc042c36fe2689801bba2ccd78
 F ext/fts5/test/fts5corrupt4.test f4c08e2182a48d8b70975fd869ee5391855c06d8a0ff87b6a2529e7c5a88a1d3
 F ext/fts5/test/fts5corrupt5.test eb6ba5ca28ef7c4c6b01e850d388cdb3dacc8c4c2f383f79d0a98128257742b4
@@ -469,7 +469,7 @@ F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c3350
 F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
 F ext/rtree/geopoly.c 971e0b5bd9adaf0811feb8c0842a310811159da10319eb0e74fdb42bf26b99ca
-F ext/rtree/rtree.c c7c7bb528a88971916420f3d66514bbefeb2e4176116e0a8c548ba8ae1a0f44e
+F ext/rtree/rtree.c 31323122691113f085da3836b81a4e9548a21bbfdd86d8becbff1a1bc2617877
 F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
 F ext/rtree/rtree1.test 877d40b8b61b1f88cec9d4dc0ff8334f5b05299fac12a35141532e2881860e9d
 F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
@@ -490,8 +490,8 @@ F ext/rtree/rtreeG.test 1b9ca6e3effb48f4161edaa463ddeaa8fca4b2526d084f9cbf5dbe4e
 F ext/rtree/rtreeH.test 0885151ee8429242625600ae47142cca935332c70a06737f35af53a7bd7aaf90
 F ext/rtree/rtreeI.test 608e77f7fde9be5a12eae316baef640fffaafcfa90a3d67443e78123e19c4ca4
 F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
-F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b587936f5f6bceed
-F ext/rtree/rtreecheck.test 4e859a9cd49d2353ff10c122f72183ec37b400e35d2b0349b2e9696649b6a00e
+F ext/rtree/rtree_util.tcl 202ca70df1f0645ef9d5a2170e62d378a28098d9407f0569e85c9c1cf1bd020a
+F ext/rtree/rtreecheck.test 934546ad9b563e090ee0c5cbdc69ad014189ad76e5df7320526797a9a345661f
 F ext/rtree/rtreecirc.test aec664eb21ae943aeb344191407afff5d392d3ae9d12b9a112ced0d9c5de298e
 F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae9268332360c68c170d3d
 F ext/rtree/rtreedoc.test 27a5703cb1200f6f69051de68da546cef3dfdcf59be73afadfc50b9f9c9960d9
@@ -699,7 +699,7 @@ F src/parse.y aeb7760d41cfa86465e3adba506500c021597049fd55f82a30e5b7045862c28c
 F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75
 F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
 F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00
-F src/pragma.c 37b8fb02d090262280c86e1e2654bf59d8dbfbfe8dc6733f2b968a11374c095a
+F src/pragma.c 2e3540e0a752ba471fa72106a75e669f6e5770a4f2895cc72dc8bbf613a69287
 F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
 F src/prepare.c 80548297dc0e1fb3139cdebffb5a1bcac3dfac66d791012dd74838e70445072d
 F src/printf.c e3ba080e2f409f9bfcc8d34724e6fc160e9c718dc92d0548f6b71b8b6f860ce2
@@ -708,7 +708,7 @@ F src/resolve.c 37953a5f36c60bea413c3c04efcd433b6177009f508ef2ace0494728912fe2e9
 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
 F src/select.c e9fb48546ab1882639a3a960383f6342dddb776c0227615f8e19de51f0102f68
 F src/shell.c.in 2f9be25294b68b07e7e81f0adcec4475aba6011b64f160e414efe226910c4d7b
-F src/sqlite.h.in 73a366c1c45d5ac9888cfe81c458826a44498531d106cfb4f328193ab5f6f17d
+F src/sqlite.h.in f04f498f763b9fe36dadd62ac14553a1db60eaf0d5fa5da223d6ff50e660ca69
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 2f30b2671f4c03cd27a43f039e11251391066c97d11385f5f963bb40b03038ac
 F src/sqliteInt.h 304deb0cb33993a19545809d245a2bfd34afb77ae701087597f64c463de596cc
@@ -776,7 +776,7 @@ F src/upsert.c fa125a8d3410ce9a97b02cb50f7ae68a2476c405c76aa692d3acf6b8586e9242
 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
 F src/util.c 81f6d47ecda50b87e87f86d0bf87aac213698b3eec0d95d4cbaea971794e2e25
 F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
-F src/vdbe.c 5f49afa4c0c9123b59ee210b4d3a14d8db5b70b5431a436ec98503ff130313e7
+F src/vdbe.c d1ae563f382d31ced33122b6162160b42928c1ebd3f41425ce28c68ecc2dab56
 F src/vdbe.h 41485521f68e9437fdb7ec4a90f9d86ab294e9bb8281e33b235915e29122cfc0
 F src/vdbeInt.h 949669dfd8a41550d27dcb905b494f2ccde9a2e6c1b0b04daa1227e2e74c2b2c
 F src/vdbeapi.c 4184402246172220418c0ef49ff4cf1a19ced9a4ac6c843c2f0773fb5c543f37
@@ -1111,11 +1111,11 @@ F test/fts3aux2.test 2459e7fa3e22734aed237d1e2ae192f5541c4d8b218956ad2d90754977b
 F test/fts3b.test c15c4a9d04e210d0be67e54ce6a87b927168fbf9c1e3faec8c1a732c366fd491
 F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
 F test/fts3comp1.test a0f5b16a2df44dd0b15751787130af2183167c0c
-F test/fts3conf.test c84bbaec81281c1788aa545ac6e78a6bd6cde2bdbbce2da261690e3659f5a76b
+F test/fts3conf.test c9cd45433b6787d48a43e84949aa2eb8b3b3d242bac7276731c1476290d31f29
 F test/fts3corrupt.test 6732477c5ace050c5758a40a8b5706c8c0cccd416b9c558e0e15224805a40e57
 F test/fts3corrupt2.test e318f0676e5e78d5a4b702637e2bb25265954c08a1b1e4aaf93c7880bb0c67d0
 F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cdb764b491f
-F test/fts3corrupt4.test 589e043d1114ea02c83530e459ef5c2d6adce63094e72826ed3bceb02e795116
+F test/fts3corrupt4.test 64c6729721575e16bb7fdfc3d23092bb84ac032b0980b891a10483cb84bc1931
 F test/fts3corrupt5.test 0549f85ec4bd22e992f645f13c59b99d652f2f5e643dac75568bfd23a6db7ed5
 F test/fts3corrupt6.test f417c910254f32c0bc9ead7affa991a1d5aec35b3b32a183ffb05eea78289525
 F test/fts3cov.test 7eacdbefd756cfa4dc2241974e3db2834e9b372ca215880e00032222f32194cf
@@ -1156,13 +1156,13 @@ F test/fts3tok1.test a663f4cac22a9505400bc22aacb818d7055240409c28729669ea7d4cc21
 F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
 F test/fts3varint.test 0b84a3fd4eba8a39f3687523804d18f3b322e6d4539a55bf342079c3614f2ada
 F test/fts4aa.test 0e6bfd6a81695a39b23e448dda25d864e63dda75bde6949c45ddc95426c6c3f5
-F test/fts4check.test 6259f856604445d7b684c9b306b2efb6346834c3f50e8fc4a59a2ca6d5319ad0
+F test/fts4check.test f0ea5e5581951d8ef7a341eea14486daf6c5f516a2f3273b0d5e8cb8a6cd3bd2
 F test/fts4content.test 73bbb123420d2c46ef2fb3b24761e9acdb78b0877179d3a5d7d57aada08066f6
 F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
 F test/fts4growth.test 289833c34ad45a5e6e6133b53b6a71647231fb89d36ddcb8d9c87211b6721d7f
 F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269
 F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d
-F test/fts4langid.test 89e623218935507bca69d076ca254a7a8969dfc681c282b6374feaea8c7de784
+F test/fts4langid.test 4be912f42454998e239a2e877600263e0394afbaba03e06cedcc5a08693a345a
 F test/fts4lastrowid.test 185835895948d5325c7710649824042373b2203149abe8024a9319d25234dfd7
 F test/fts4merge.test e2b2ec21e287d54ec09824ccfb41e66896eeca568fc818ba0e0eb2efd94c35d2
 F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
@@ -2116,8 +2116,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P b12afff4efe4de84388d102060e8c312abd2f9eca8270b3c0f01ac6d1f2e329a
-R c33ff09bfe39aecbb90b639f6158696c
+P 93f74490faf8cc07e107afdab6737c6e5141ae1f01a05142bfcede2dd1b2ba4e
+R d97552325661633b153eed717efa1718
+T *branch * vtab-integrity-check
+T *sym-vtab-integrity-check *
+T -sym-trunk *
 U drh
-Z 799fbc495b6d502c0a1ef040c8c3f7ec
+Z a0732a36eef9f82a0ff5fe63847cfd5b
 # Remove this line to create a well-formed Fossil manifest.
index 98d9d4265cfa8b409752511aa218e99d8618aadf..652d256588b41578c0283139b7b28060c23c3990 100644 (file)
@@ -1 +1 @@
-93f74490faf8cc07e107afdab6737c6e5141ae1f01a05142bfcede2dd1b2ba4e
\ No newline at end of file
+17bede8cdefd968210dd8a5a2617acbe12ba2c99fdd5e88c5def8665e7bec2d7
\ No newline at end of file
index f15c1be279570d0ae2c72d3145501dd7902fcac9..db6fc04a821e2fc35a44660292188b7bc2f07f03 100644 (file)
@@ -1757,8 +1757,24 @@ void sqlite3Pragma(
         int r2;                 /* Previous key for WITHOUT ROWID tables */
         int mxCol;              /* Maximum non-virtual column number */
 
-        if( !IsOrdinaryTable(pTab) ) continue;
         if( pObjTab && pObjTab!=pTab ) continue;
+        if( !IsOrdinaryTable(pTab) ){
+          sqlite3_vtab *pVTab;
+          int a1;
+          if( !IsVirtual(pTab) ) continue;
+          if( pTab->u.vtab.p==0 ) continue;
+          pVTab = pTab->u.vtab.p->pVtab;
+          if( NEVER(pVTab==0) ) continue;
+          if( pVTab->pModule==0 ) continue;
+          if( pVTab->pModule->iVersion<4 ) continue;
+          if( pVTab->pModule->xIntegrity==0 ) continue;
+          sqlite3VdbeAddOp2(v, OP_VCheck, 0, 3);
+          sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
+          a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3);
+          integrityCheckResultRow(v);
+          sqlite3VdbeJumpHere(v, a1);
+          continue;
+        }
         if( isQuick || HasRowid(pTab) ){
           pPk = 0;
           r2 = 0;
index 48009b1454afe3a9b5baecf2c78708270f0c5e68..e2afe5b669c91ef1163622337660fc260c5fb592 100644 (file)
@@ -7217,6 +7217,9 @@ struct sqlite3_module {
   /* The methods above are in versions 1 and 2 of the sqlite_module object.
   ** Those below are for version 3 and greater. */
   int (*xShadowName)(const char*);
+  /* The methods above are in versions 1 through 3 of the sqlite_module object.
+  ** Those below are for version 4 and greater. */
+  char *(*xIntegrity)(sqlite3_vtab *pVTab);
 };
 
 /*
index 4e681d41c86df2822f878f7a73209579747b7a97..73682be85f40b54ec9d25cb58ecda502f98f56a7 100644 (file)
@@ -8128,6 +8128,42 @@ case OP_VOpen: {             /* ncycle */
 }
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
 
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VCheck * P2 * P4 *
+**
+** P4 is a pointer to a Table object that is a virtual table that
+** supports the xIntegrity() method.  This opcode runs the xIntegrity()
+** method for that virtual table.  If an error is reported back, the error
+** message is stored in register P2.  If no errors are seen, register P2
+** is set to NULL.
+*/
+case OP_VCheck: {             /* out2 */
+  Table *pTab;
+  sqlite3_vtab *pVtab;
+  const sqlite3_module *pModule;
+  char *zErr;
+
+  pOut = &aMem[pOp->p2];
+  sqlite3VdbeMemSetNull(pOut);  /* Innocent until proven guilty */
+  assert( pOp->p4type==P4_TABLE );
+  pTab = pOp->p4.pTab;
+  assert( pTab!=0 );
+  assert( IsVirtual(pTab) );
+  assert( pTab->u.vtab.p!=0 );
+  pVtab = pTab->u.vtab.p->pVtab;
+  assert( pVtab!=0 );
+  pModule = pVtab->pModule;
+  assert( pModule!=0 );
+  assert( pModule->iVersion>=4 );
+  assert( pModule->xIntegrity!=0 );
+  zErr = pModule->xIntegrity(pVtab);
+  if( zErr ){
+    sqlite3VdbeMemSetStr(pOut, zErr, -1, SQLITE_UTF8, sqlite3_free);
+  }
+  break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
 #ifndef SQLITE_OMIT_VIRTUALTABLE
 /* Opcode: VInitIn P1 P2 P3 * *
 ** Synopsis: r[P2]=ValueList(P1,P3)
index 6ceef2c47ef08ff6a0aa7f6a33b7f06f7601ba3f..cd48290195d8d517a9e723d2203763e51d2e7e89 100644 (file)
@@ -198,7 +198,8 @@ do_execsql_test 4.1.2 {
 do_execsql_test 4.1.3 {
   SELECT * FROM t0 WHERE t0 MATCH 'abc';
   INSERT INTO t0(t0) VALUES('integrity-check');
-} {}
+  PRAGMA integrity_check;
+} {ok}
 
 do_execsql_test 4.2.1 {
   CREATE VIRTUAL TABLE t01 USING fts4;
@@ -211,7 +212,8 @@ do_execsql_test 4.2.1 {
 do_execsql_test 4.2.2 {
   SELECT * FROM t01 WHERE t01 MATCH 'b';
   INSERT INTO t01(t01) VALUES('integrity-check');
-} {}
+  PRAGMA integrity_check;
+} {ok}
 
 do_execsql_test 4.3.1 {
   CREATE VIRTUAL TABLE t02 USING fts4;
index f8e89b3a7510dd2c00811848c032ca5423f24975..74aaa18fb8f282a08ed8645152c84ba484c9e727 100644 (file)
@@ -5812,6 +5812,9 @@ do_execsql_test 35.0 {
 do_catchsql_test 35.1 {
   INSERT INTO f(f) VALUES ('integrity-check');
 } {1 {database disk image is malformed}}
+do_execsql_test 35.2 {
+  PRAGMA integrity_check;
+} {{malformed inverted index for FTS3 table main.f}}
 
 reset_db
 do_catchsql_test 36.0 {
index c94c35910bd24e2edfcb5f3627ea7fb78762371f..7f1004d8b30fce46c6808ce30d413b80dc55965a 100644 (file)
@@ -71,7 +71,10 @@ foreach {tn disruption} {
   do_catchsql_test 1.2.2.$tn {
     INSERT INTO t1 (t1) VALUES('integrity-check')
   } {1 {database disk image is malformed}}
-  do_execsql_test  1.2.3.$tn "ROLLBACK"
+  do_execsql_test 1.2.3.$tn {
+    PRAGMA integrity_check;
+  } {{malformed inverted index for FTS4 table main.t1}}
+  do_execsql_test  1.2.4.$tn "ROLLBACK"
 }
 
 do_test 1.3 { fts_integrity db t1 } {ok}
@@ -106,7 +109,10 @@ foreach {tn disruption} {
   do_catchsql_test 2.2.2.$tn {
     INSERT INTO t2 (t2) VALUES('integrity-check')
   } {1 {database disk image is malformed}}
-  do_execsql_test  2.2.3.$tn "ROLLBACK"
+  do_test 2.2.3.$tn {
+    db eval {PRAGMA integrity_check(t2);}
+  } {{malformed inverted index for FTS4 table main.t2}}
+  do_execsql_test  2.2.4.$tn "ROLLBACK"
 }
 
 
index 45e851f940a924ba7c718410122a0715e2bdbd8b..7be594bd5f374733a99cb050bacb8cb08c2028fb 100644 (file)
@@ -499,7 +499,8 @@ do_execsql_test 6.0 {
 }
 do_execsql_test 6.1 {
   INSERT INTO vt0(vt0) VALUES('integrity-check');
-}
+  PRAGMA integrity_check;
+} {ok}
 do_execsql_test 6.2 {
   COMMIT;
   INSERT INTO vt0(vt0) VALUES('integrity-check');