]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Use more efficient SQL to verify that indexes contain entries that match their tables.
authordan <Dan Kennedy>
Mon, 19 Feb 2024 20:15:44 +0000 (20:15 +0000)
committerdan <Dan Kennedy>
Mon, 19 Feb 2024 20:15:44 +0000 (20:15 +0000)
FossilOrigin-Name: c01e008c28895e50b14531b2a1f3f1110aab3b54df41ebdbd416fbac7b1bba94

ext/intck/sqlite3intck.c
ext/intck/sqlite3intck.h
ext/intck/test_intck.c
manifest
manifest.uuid

index b08b499a4370d27a8c6dd5505d99b9464d0de2e6..05eaa81a9347d18d54a58713e66060cb7d1e2997 100644 (file)
 struct sqlite3_intck {
   sqlite3 *db;
   const char *zDb;                /* Copy of zDb parameter to _open() */
-
   char *zObj;                     /* Current object. Or NULL. */
-  char *zKey;                     /* Key saved by _suspect() call. */
-
-  sqlite3_stmt *pCheck;
-
-  int rc;                         /* SQLite error code */
+  char *zKey;                     /* Key saved by _intck_suspend() call. */
+  sqlite3_stmt *pCheck;           /* Current check statement */
+  int rc;                         /* Error code */
   char *zErr;                     /* Error message */
-
   char *zTestSql;                 /* Returned by sqlite3_intck_test_sql() */
 };
 
@@ -109,7 +105,7 @@ static void intckFindObject(sqlite3_intck *p){
   pStmt = intckPrepare(p, 
     "WITH tables(table_name) AS (" 
     "  SELECT name"
-    "  FROM %Q.sqlite_schema WHERE type='table' OR type='index'"
+    "  FROM %Q.sqlite_schema WHERE (type='table' OR type='index') AND rootpage"
     "  UNION ALL "
     "  SELECT 'sqlite_schema'"
     ")"
@@ -400,9 +396,9 @@ static char *intckCheckObjectSql(
       ""
       ", idx(name, match_expr, partial, partial_alias, idx_ps, idx_idx) AS ("
       "  SELECT idx_name,"
-      "    format('(%s) IS (%s)', "
-      "           group_concat(i.col_expr, ', '),"
-      "           group_concat('o.'||i.col_alias, ', ')"
+      "    format('(%s,%s) IS (%s,%s)', "
+      "           group_concat(i.col_expr, ', '), i_pk,"
+      "           group_concat('o.'||i.col_alias, ', '), o_pk"
       "    ), "
       "    parse_create_index("
       "        (SELECT sql FROM sqlite_schema WHERE name=idx_name), -1"
@@ -512,13 +508,12 @@ static char *intckCheckObjectSql(
       ** is set to an expression that evaluates to NULL if the required
       ** entry is present in the index, or an error message otherwise.  */
       ", expr(e, p) AS ("
-      "  SELECT format('CASE WHEN (%%s) IN\n"
-      "    (SELECT %%s FROM %%Q.%%Q AS i INDEXED BY %%Q WHERE %%s%%s)\n"
+      "  SELECT format('CASE WHEN EXISTS \n"
+      "    (SELECT 1 FROM %%Q.%%Q AS i INDEXED BY %%Q WHERE %%s%%s)\n"
       "    THEN NULL\n"
       "    ELSE format(''entry (%%s,%%s) missing from index %%s'', %%s, %%s)\n"
       "  END\n'"
-      "    , t.o_pk, t.i_pk, t.db, t.tab, i.name, i.match_expr, "
-      "    ' AND (' || partial || ')',"
+      "    , t.db, t.tab, i.name, i.match_expr, ' AND (' || partial || ')',"
       "      i.idx_ps, t.ps_pk, i.name, i.idx_idx, t.pk_pk),"
       "    CASE WHEN partial IS NULL THEN NULL ELSE i.partial_alias END"
       "  FROM tabpk t, idx i"
@@ -626,30 +621,35 @@ int sqlite3_intck_open(
   if( pNew==0 ){
     rc = SQLITE_NOMEM;
   }else{
+    sqlite3_create_function(db, "parse_create_index", 
+        2, SQLITE_UTF8, 0, parseCreateIndexFunc, 0, 0
+    );
     memset(pNew, 0, sizeof(*pNew));
     pNew->db = db;
     pNew->zDb = (const char*)&pNew[1];
     memcpy(&pNew[1], zDb, nDb+1);
-    sqlite3_create_function(db, "parse_create_index", 
-        2, SQLITE_UTF8, 0, parseCreateIndexFunc, 0, 0
-    );
   }
 
   *ppOut = pNew;
   return rc;
 }
 
-void sqlite3_intck_close(sqlite3_intck *p){
-  if( p && p->db ){
-    sqlite3_create_function(
-        p->db, "parse_create_index", 1, SQLITE_UTF8, 0, 0, 0, 0
-    );
+int sqlite3_intck_close(sqlite3_intck *p){
+  int rc = SQLITE_OK;
+  if( p ){
+    rc = (p->rc==SQLITE_DONE ? SQLITE_OK : p->rc);
+    if( p->db ){
+      sqlite3_create_function(
+          p->db, "parse_create_index", 1, SQLITE_UTF8, 0, 0, 0, 0
+      );
+    }
+    sqlite3_free(p->zObj);
+    sqlite3_free(p->zKey);
+    sqlite3_free(p->zTestSql);
+    sqlite3_free(p->zErr);
+    sqlite3_free(p);
   }
-  sqlite3_free(p->zObj);
-  sqlite3_free(p->zKey);
-  sqlite3_free(p->zTestSql);
-  sqlite3_free(p->zErr);
-  sqlite3_free(p);
+  return rc;
 }
 
 int sqlite3_intck_step(sqlite3_intck *p){
index 8846812e75319066af01b5d9091829863a997128..c7c24e42c9755cf9e82d74b0f1ab81b98c3bacb4 100644 (file)
@@ -29,7 +29,7 @@ int sqlite3_intck_open(
   sqlite3_intck **ppOut
 );
 
-void sqlite3_intck_close(sqlite3_intck*);
+int sqlite3_intck_close(sqlite3_intck*);
 
 int sqlite3_intck_step(sqlite3_intck *pCk);
 
index d14fc92a6c97a8c1813333208e7ff0868e2265ea..75bcfa298abb7e5f989b0f3e4ab44efe46be9e1e 100644 (file)
@@ -179,7 +179,60 @@ static int test_sqlite3_intck(
   return TCL_OK;
 }
 
+/*
+** tclcmd: test_do_intck DB DBNAME
+*/
+static int test_do_intck(
+  void * clientData,
+  Tcl_Interp *interp,
+  int objc,
+  Tcl_Obj *CONST objv[]
+){
+  sqlite3 *db = 0;
+  const char *zDb = 0;
+  int rc = SQLITE_OK;
+  sqlite3_intck *pCk = 0;
+  Tcl_Obj *pRet = 0;
+  const char *zErr = 0;
+
+  if( objc!=3 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
+    return TCL_ERROR;
+  }
+  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
+    return TCL_ERROR;
+  }
+  zDb = Tcl_GetString(objv[2]);
+
+  pRet = Tcl_NewObj();
+  Tcl_IncrRefCount(pRet);
+
+  rc = sqlite3_intck_open(db, zDb, 0, &pCk);
+  if( rc==SQLITE_OK ){
+    while( sqlite3_intck_step(pCk)==SQLITE_OK ){
+      const char *zMsg = sqlite3_intck_message(pCk);
+      if( zMsg ){
+        Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(zMsg, -1));
+      }
+    }
+    rc = sqlite3_intck_error(pCk, &zErr);
+  }
+  if( rc!=SQLITE_OK ){
+    if( zErr ){
+      Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
+    }else{
+      Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
+    }
+  }else{
+    Tcl_SetObjResult(interp, pRet);
+  }
+  Tcl_DecrRefCount(pRet);
+  sqlite3_intck_close(pCk);
+  return rc ? TCL_ERROR : TCL_OK;
+}
+
 int Sqlitetestintck_Init(Tcl_Interp *interp){
   Tcl_CreateObjCommand(interp, "sqlite3_intck", test_sqlite3_intck, 0, 0);
+  Tcl_CreateObjCommand(interp, "test_do_intck", test_do_intck, 0, 0);
   return TCL_OK;
 }
index bb8e46b123ef1964495323cb2639128aecef4244..cf377664707391536088af9e5fcfd52cf1d25426 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\simplementation\sof\ssqlite3_intck_suspend().
-D 2024-02-19T18:03:53.963
+C Use\smore\sefficient\sSQL\sto\sverify\sthat\sindexes\scontain\sentries\sthat\smatch\stheir\stables.
+D 2024-02-19T20:15:44.802
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -251,9 +251,9 @@ F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a3
 F ext/intck/intck1.test c831bc6ff67da3c5b6c9568640f87ad0442d4fc98ef97bc837133b94bcc645b3
 F ext/intck/intck2.test b65d7f627342f767e1d2c447d25619666cec36f516786dd56568bd741e5d7e67
 F ext/intck/intck_common.tcl 2895854e7aaf5e199a15f6f82538a00999fd8fc55553bc1f04619af7aa86c0d0
-F ext/intck/sqlite3intck.c 703ff16bc936192cff20d06b015d66279f4594e88371c00b18d17fec4f01ff5c
-F ext/intck/sqlite3intck.h 342ee2e2c7636b4daf29fa195d0a3a658272b76b283d586fba50f6bc80fc143d
-F ext/intck/test_intck.c eb596269c4a690a9b8ee689b1e52ff6e3306013ec706e319d5b97af05a08f0b9
+F ext/intck/sqlite3intck.c 5f319b7c72b0c01cfa28bb5fdd19be5781eb11f5a5216af2a0870dc7e001414d
+F ext/intck/sqlite3intck.h d9501ea480b7c41c0555f39f4f1b7c3e8d54fc1ea6d115de5e1211e0bc11d3e7
+F ext/intck/test_intck.c 06206b35f1428961015c060dd35201246c849625cfdff461e0eeaaf76bda545c
 F ext/jni/GNUmakefile 59eb05f2a363bdfac8d15d66bed624bfe1ff289229184f3861b95f98a19cf4b2
 F ext/jni/README.md d899789a9082a07b99bf30b1bbb6204ae57c060efcaa634536fa669323918f42
 F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa
@@ -2168,8 +2168,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 444e3c9210026da7eae1ed98850722e002433aa2cc77dbc6b6f80327a6b7a390
-R 6b69910b5d388b58f98078e173b37781
+P c36ada868da74e030ff5002de1f3b31b639b0c43714b91c2e5ca0eda16bb6bc2
+R 830041ceb0564db12655be53580aeb6a
 U dan
-Z 3045521be4122627d743cbd6c4ab9b9c
+Z f8e44044aacffa331f677c80763fe8b6
 # Remove this line to create a well-formed Fossil manifest.
index fa3faa50cddd2407c989f0caad2257961179e690..eb805d0954eaaa4468ca3204fd6df83ce96f0bd4 100644 (file)
@@ -1 +1 @@
-c36ada868da74e030ff5002de1f3b31b639b0c43714b91c2e5ca0eda16bb6bc2
\ No newline at end of file
+c01e008c28895e50b14531b2a1f3f1110aab3b54df41ebdbd416fbac7b1bba94
\ No newline at end of file