]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Changes to allow the code in sqlite3expert.c to be tested directly (via the
authordan <dan@noemail.net>
Mon, 10 Apr 2017 16:13:20 +0000 (16:13 +0000)
committerdan <dan@noemail.net>
Mon, 10 Apr 2017 16:13:20 +0000 (16:13 +0000)
API in sqlite3expert.h) instead of by invoking the sqlite3_expert application.
Fix memory leaks and other problems.

FossilOrigin-Name: 5dd9831721b70a89a26728adcd49c7f6103ef8266891a79c2db34d913702709e

ext/expert/expert1.test [moved from test/expert1.test with 74% similarity]
ext/expert/sqlite3expert.c
ext/expert/test_expert.c [new file with mode: 0644]
main.mk
manifest
manifest.uuid
src/tclsqlite.c
test/permutations.test

similarity index 74%
rename from test/expert1.test
rename to ext/expert/expert1.test
index b5651040d8c002c469f15f496bae05901c79be03..684c6187807f3f306ae42af7406a98f3a040237a 100644 (file)
@@ -26,39 +26,62 @@ if {$tcl_platform(platform)=="windows"} {
 } else {
   set CMD ".././sqlite3_expert"
 }
-if {![file executable $CMD]} {
-  finish_test
-  return
-}
-
 
 proc squish {txt} {
   regsub -all {[[:space:]]+} $txt { }
 }
 
-proc do_rec_test {tn sql res} {
-  set res [squish [string trim $res]]
-  set tst [subst -nocommands { 
-    squish [string trim [exec $::CMD -verbose 0 -sql {$sql;} test.db]]
-  }]
-  uplevel [list do_test $tn $tst $res]
-}
-
 proc do_setup_rec_test {tn setup sql res} {
   reset_db
   db eval $setup
   uplevel [list do_rec_test $tn $sql $res]
 }
 
+foreach {tn setup} {
+  1 {
+    if {![file executable $CMD]} { continue }
+
+    proc do_rec_test {tn sql res} {
+      set res [squish [string trim $res]]
+      set tst [subst -nocommands { 
+        squish [string trim [exec $::CMD -verbose 0 -sql {$sql;} test.db]]
+      }]
+      uplevel [list do_test $tn $tst $res]
+    }
+  }
+  2 {
+    if {[info commands sqlite3_expert_new]==""} { continue }
+
+    proc do_rec_test {tn sql res} {
+      set expert [sqlite3_expert_new db]
+      $expert sql $sql
+      $expert analyze
+
+      set result [list]
+      for {set i 0} {$i < [$expert count]} {incr i} {
+        lappend result [string trim [$expert report $i indexes]]
+        lappend result [string trim [$expert report $i plan]]
+      }
 
-do_setup_rec_test 1.1 { CREATE TABLE t1(a, b, c) } {
+      $expert destroy
+
+      set tst [subst -nocommands {set {} [squish [join {$result}]]}]
+      uplevel [list do_test $tn $tst [string trim [squish $res]]]
+    }
+  }
+} {
+
+  eval $setup
+
+
+do_setup_rec_test $tn.1.1 { CREATE TABLE t1(a, b, c) } {
   SELECT * FROM t1
 } {
   (no new indexes)
   0|0|0|SCAN TABLE t1
 }
 
-do_setup_rec_test 1.2 {
+do_setup_rec_test $tn.1.2 {
   CREATE TABLE t1(a, b, c);
 } {
   SELECT * FROM t1 WHERE b>?;
@@ -67,7 +90,7 @@ do_setup_rec_test 1.2 {
   0|0|0|SEARCH TABLE t1 USING INDEX t1_idx_00000062 (b>?)
 }
 
-do_setup_rec_test 1.3 {
+do_setup_rec_test $tn.1.3 {
   CREATE TABLE t1(a, b, c);
 } {
   SELECT * FROM t1 WHERE b COLLATE nocase BETWEEN ? AND ?
@@ -76,7 +99,7 @@ do_setup_rec_test 1.3 {
   0|0|0|SEARCH TABLE t1 USING INDEX t1_idx_3e094c27 (b>? AND b<?)
 }
 
-do_setup_rec_test 1.4 {
+do_setup_rec_test $tn.1.4 {
   CREATE TABLE t1(a, b, c);
 } {
   SELECT a FROM t1 ORDER BY b;
@@ -85,7 +108,7 @@ do_setup_rec_test 1.4 {
   0|0|0|SCAN TABLE t1 USING INDEX t1_idx_00000062
 }
 
-do_setup_rec_test 1.5 {
+do_setup_rec_test $tn.1.5 {
   CREATE TABLE t1(a, b, c);
 } {
   SELECT a FROM t1 WHERE a=? ORDER BY b;
@@ -94,7 +117,7 @@ do_setup_rec_test 1.5 {
   0|0|0|SEARCH TABLE t1 USING COVERING INDEX t1_idx_000123a7 (a=?)
 }
 
-do_setup_rec_test 1.6 {
+do_setup_rec_test $tn.1.6 {
   CREATE TABLE t1(a, b, c);
 } {
   SELECT min(a) FROM t1
@@ -103,7 +126,7 @@ do_setup_rec_test 1.6 {
   0|0|0|SEARCH TABLE t1 USING COVERING INDEX t1_idx_00000061
 }
 
-do_setup_rec_test 1.7 {
+do_setup_rec_test $tn.1.7 {
   CREATE TABLE t1(a, b, c);
 } {
   SELECT * FROM t1 ORDER BY a, b, c;
@@ -112,7 +135,7 @@ do_setup_rec_test 1.7 {
   0|0|0|SCAN TABLE t1 USING COVERING INDEX t1_idx_033e95fe
 }
 
-do_setup_rec_test 1.8 {
+do_setup_rec_test $tn.1.8 {
   CREATE TABLE t1(a, b, c);
 } {
   SELECT * FROM t1 ORDER BY a ASC, b COLLATE nocase DESC, c ASC;
@@ -121,7 +144,7 @@ do_setup_rec_test 1.8 {
   0|0|0|SCAN TABLE t1 USING COVERING INDEX t1_idx_5be6e222
 }
 
-do_setup_rec_test 1.9 {
+do_setup_rec_test $tn.1.9 {
   CREATE TABLE t1(a COLLATE NOCase, b, c);
 } {
   SELECT * FROM t1 WHERE a=?
@@ -133,7 +156,7 @@ do_setup_rec_test 1.9 {
 
 # Tables with names that require quotes.
 #
-do_setup_rec_test 8.1 {
+do_setup_rec_test $tn.8.1 {
   CREATE TABLE "t t"(a, b, c);
 } {
   SELECT * FROM "t t" WHERE a=?
@@ -142,7 +165,7 @@ do_setup_rec_test 8.1 {
   0|0|0|SEARCH TABLE t t USING INDEX t t_idx_00000061 (a=?) 
 }
 
-do_setup_rec_test 8.2 {
+do_setup_rec_test $tn.8.2 {
   CREATE TABLE "t t"(a, b, c);
 } {
   SELECT * FROM "t t" WHERE b BETWEEN ? AND ?
@@ -153,7 +176,7 @@ do_setup_rec_test 8.2 {
 
 # Columns with names that require quotes.
 #
-do_setup_rec_test 9.1 {
+do_setup_rec_test $tn.9.1 {
   CREATE TABLE t3(a, "b b", c);
 } {
   SELECT * FROM t3 WHERE "b b" = ?
@@ -162,7 +185,7 @@ do_setup_rec_test 9.1 {
   0|0|0|SEARCH TABLE t3 USING INDEX t3_idx_00050c52 (b b=?)
 }
 
-do_setup_rec_test 9.2 {
+do_setup_rec_test $tn.9.2 {
   CREATE TABLE t3(a, "b b", c);
 } {
   SELECT * FROM t3 ORDER BY "b b"
@@ -173,7 +196,7 @@ do_setup_rec_test 9.2 {
 
 # Transitive constraints
 #
-do_setup_rec_test 10.1 {
+do_setup_rec_test $tn.10.1 {
   CREATE TABLE t5(a, b);
   CREATE TABLE t6(c, d);
 } {
@@ -187,7 +210,7 @@ do_setup_rec_test 10.1 {
 
 # OR terms.
 #
-do_setup_rec_test 11.1 {
+do_setup_rec_test $tn.11.1 {
   CREATE TABLE t7(a, b);
 } {
   SELECT * FROM t7 WHERE a=? OR b=?
@@ -198,5 +221,7 @@ do_setup_rec_test 11.1 {
   0|0|0|SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?)
 }
 
+}
+
 finish_test
 
index 6d674a748ba454de35f3985633c06b4fb1c0728b..6bcc697fcf58581c28543f1e0a258a7cf8453ded 100644 (file)
@@ -11,6 +11,8 @@
 *************************************************************************
 */
 
+#if !defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHEREINFO_HOOK)
+
 #include "sqlite3expert.h"
 #include <assert.h>
 #include <string.h>
@@ -20,7 +22,6 @@ typedef sqlite3_int64 i64;
 typedef sqlite3_uint64 u64;
 
 typedef struct IdxConstraint IdxConstraint;
-typedef struct IdxContext IdxContext;
 typedef struct IdxScan IdxScan;
 typedef struct IdxStatement IdxStatement;
 typedef struct IdxWhere IdxWhere;
@@ -89,19 +90,6 @@ struct IdxTable {
   IdxColumn *aCol;
 };
 
-/*
-** Context object passed to idxWhereInfo() and other functions.
-*/
-struct IdxContext {
-  char **pzErrmsg;
-  IdxWhere *pCurrent;             /* Current where clause */
-  int rc;                         /* Error code (if error has occurred) */
-  IdxScan *pScan;                 /* List of scan objects */
-  sqlite3 *dbm;                   /* In-memory db for this analysis */
-  sqlite3 *db;                    /* User database under analysis */
-  sqlite3_stmt *pInsertMask;      /* To write to aux.depmask */
-};
-
 struct IdxStatement {
   int iId;                        /* Statement number */
   char *zSql;                     /* SQL statement */
@@ -301,7 +289,7 @@ static IdxConstraint *idxNewConstraint(int *pRc, const char *zColl){
 ** sqlite3_whereinfo_hook() callback.
 */
 static void idxWhereInfo(
-  void *pCtx,                     /* Pointer to IdxContext structure */
+  void *pCtx,                     /* Pointer to sqlite3expert structure */
   int eOp, 
   const char *zVal, 
   int iVal, 
@@ -794,12 +782,31 @@ static int idxCreateCandidates(sqlite3expert *p, char **pzErr){
   return rc;
 }
 
+static void idxConstraintFree(IdxConstraint *pConstraint){
+  IdxConstraint *pNext;
+  IdxConstraint *p;
+
+  for(p=pConstraint; p; p=pNext){
+    pNext = p->pNext;
+    sqlite3_free(p);
+  }
+}
+
 /*
 ** Free all elements of the linked list starting from pScan up until pLast
 ** (pLast is not freed).
 */
 static void idxScanFree(IdxScan *pScan, IdxScan *pLast){
-  /* TODO! */
+  IdxScan *p;
+  IdxScan *pNext;
+  for(p=pScan; p!=pLast; p=pNext){
+    pNext = p->pNextScan;
+    idxConstraintFree(p->pOrder);
+    idxConstraintFree(p->where.pEq);
+    idxConstraintFree(p->where.pRange);
+    sqlite3_free(p->pTable);
+    sqlite3_free(p);
+  }
 }
 
 /*
@@ -807,7 +814,14 @@ static void idxScanFree(IdxScan *pScan, IdxScan *pLast){
 ** until pLast (pLast is not freed).
 */
 static void idxStatementFree(IdxStatement *pStatement, IdxStatement *pLast){
-  /* TODO! */
+  IdxStatement *p;
+  IdxStatement *pNext;
+  for(p=pStatement; p!=pLast; p=pNext){
+    pNext = p->pNext;
+    sqlite3_free(p->zEQP);
+    sqlite3_free(p->zIdx);
+    sqlite3_free(p);
+  }
 }
 
 
@@ -875,6 +889,7 @@ int idxFindIndexes(
   }
 
  find_indexes_out:
+  idxHashClear(&hIdx);
   return rc;
 }
 
@@ -974,7 +989,6 @@ int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr){
     rc = idxGetTableInfo(p->dbm, pIter, pzErr);
   }
 
-
   /* Create candidate indexes within the in-memory database file */
   if( rc==SQLITE_OK ){
     rc = idxCreateCandidates(p, pzErr);
@@ -992,12 +1006,19 @@ int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr){
   return rc;
 }
 
+/*
+** Return the total number of statements that have been added to this
+** sqlite3expert using sqlite3_expert_sql().
+*/
 int sqlite3_expert_count(sqlite3expert *p){
   int nRet = 0;
   if( p->pStatement ) nRet = p->pStatement->iId+1;
   return nRet;
 }
 
+/*
+** Return a component of the report.
+*/
 const char *sqlite3_expert_report(sqlite3expert *p, int iStmt, int eReport){
   const char *zRet = 0;
   IdxStatement *pStmt;
@@ -1027,6 +1048,9 @@ void sqlite3_expert_destroy(sqlite3expert *p){
   sqlite3_close(p->dbm);
   idxScanFree(p->pScan, 0);
   idxStatementFree(p->pStatement, 0);
+  idxHashClear(&p->hIdx);
   sqlite3_free(p);
 }
 
+#endif /* !defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHEREINFO_HOOK) */
+
diff --git a/ext/expert/test_expert.c b/ext/expert/test_expert.c
new file mode 100644 (file)
index 0000000..a37887e
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+** 2017 April 07
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+*/
+
+#if defined(SQLITE_TEST) && defined(SQLITE_ENABLE_WHEREINFO_HOOK)
+
+#include "sqlite3expert.h"
+#include <assert.h>
+#include <string.h>
+
+#if defined(INCLUDE_SQLITE_TCL_H)
+#  include "sqlite_tcl.h"
+#else
+#  include "tcl.h"
+#  ifndef SQLITE_TCLAPI
+#    define SQLITE_TCLAPI
+#  endif
+#endif
+
+/*
+** Extract an sqlite3* db handle from the object passed as the second
+** argument. If successful, set *pDb to point to the db handle and return
+** TCL_OK. Otherwise, return TCL_ERROR.
+*/
+static int dbHandleFromObj(Tcl_Interp *interp, Tcl_Obj *pObj, sqlite3 **pDb){
+  Tcl_CmdInfo info;
+  if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(pObj), &info) ){
+    Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(pObj), 0);
+    return TCL_ERROR;
+  }
+
+  *pDb = *(sqlite3 **)info.objClientData;
+  return TCL_OK;
+}
+
+
+/*
+** Tclcmd:  $expert sql SQL
+**          $expert analyze
+**          $expert count
+**          $expert report STMT EREPORT
+**          $expert destroy
+*/
+static int SQLITE_TCLAPI testExpertCmd(
+  void *clientData,
+  Tcl_Interp *interp,
+  int objc,
+  Tcl_Obj *CONST objv[]
+){
+  sqlite3expert *pExpert = (sqlite3expert*)clientData;
+  struct Subcmd {
+    const char *zSub;
+    int nArg;
+    const char *zMsg;
+  } aSub[] = {
+    { "sql",       1, "TABLE",        }, /* 0 */
+    { "analyze",   0, "",             }, /* 1 */
+    { "count",     0, "",             }, /* 2 */
+    { "report",    2, "STMT EREPORT", }, /* 3 */
+    { "destroy",   0, "",             }, /* 4 */
+    { 0 }
+  };
+  int iSub;
+  int rc = TCL_OK;
+  char *zErr = 0;
+
+  if( objc<2 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
+    return TCL_ERROR;
+  }
+  rc = Tcl_GetIndexFromObjStruct(interp, 
+      objv[1], aSub, sizeof(aSub[0]), "sub-command", 0, &iSub
+  );
+  if( rc!=TCL_OK ) return rc;
+  if( objc!=2+aSub[iSub].nArg ){
+    Tcl_WrongNumArgs(interp, 2, objv, aSub[iSub].zMsg);
+    return TCL_ERROR;
+  }
+
+  switch( iSub ){
+    case 0: {      /* sql */
+      char *zArg = Tcl_GetString(objv[2]);
+      rc = sqlite3_expert_sql(pExpert, zArg, &zErr);
+      break;
+    }
+
+    case 1: {      /* analyze */
+      rc = sqlite3_expert_analyze(pExpert, &zErr);
+      break;
+    }
+
+    case 2: {      /* count */
+      int n = sqlite3_expert_count(pExpert);
+      Tcl_SetObjResult(interp, Tcl_NewIntObj(n));
+      break;
+    }
+
+    case 3: {      /* report */
+      const char *aEnum[] = {
+        "sql", "indexes", "plan", 0
+      };
+      int iEnum;
+      int iStmt;
+      const char *zReport;
+
+      if( Tcl_GetIntFromObj(interp, objv[2], &iStmt) 
+       || Tcl_GetIndexFromObj(interp, objv[3], aEnum, "report", 0, &iEnum)
+      ){
+        return TCL_ERROR;
+      }
+
+      assert( EXPERT_REPORT_SQL==1 );
+      assert( EXPERT_REPORT_INDEXES==2 );
+      assert( EXPERT_REPORT_PLAN==3 );
+      zReport = sqlite3_expert_report(pExpert, iStmt, 1+iEnum);
+      Tcl_SetObjResult(interp, Tcl_NewStringObj(zReport, -1));
+      break;
+    }
+
+    default:       /* destroy */
+      assert( iSub==4 );     
+      Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
+      break;
+  }
+
+  if( rc!=TCL_OK ){
+    if( zErr ){
+      Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
+    }else{
+      extern const char *sqlite3ErrName(int);
+      Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
+    }
+  }
+  sqlite3_free(zErr);
+  return rc;
+}
+
+static void SQLITE_TCLAPI testExpertDel(void *clientData){
+  sqlite3expert *pExpert = (sqlite3expert*)clientData;
+  sqlite3_expert_destroy(pExpert);
+}
+
+/*
+** sqlite3_expert_new DB
+*/
+static int SQLITE_TCLAPI test_sqlite3_expert_new(
+  void * clientData,
+  Tcl_Interp *interp,
+  int objc,
+  Tcl_Obj *CONST objv[]
+){
+  static int iCmd = 0;
+  sqlite3 *db;
+  char *zCmd = 0;
+  char *zErr = 0;
+  sqlite3expert *pExpert;
+  int rc = TCL_OK;
+
+  if( objc!=2 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "DB");
+    return TCL_ERROR;
+  }
+  if( dbHandleFromObj(interp, objv[1], &db) ){
+    return TCL_ERROR;
+  }
+
+  zCmd = sqlite3_mprintf("sqlite3expert%d", ++iCmd);
+  if( zCmd==0 ){
+    Tcl_AppendResult(interp, "out of memory", (char*)0);
+    return TCL_ERROR;
+  }
+
+  pExpert = sqlite3_expert_new(db, &zErr);
+  if( pExpert==0 ){
+    Tcl_AppendResult(interp, zErr, (char*)0);
+    rc = TCL_ERROR;
+  }else{
+    void *p = (void*)pExpert;
+    Tcl_CreateObjCommand(interp, zCmd, testExpertCmd, p, testExpertDel);
+    Tcl_SetObjResult(interp, Tcl_NewStringObj(zCmd, -1));
+  }
+
+  sqlite3_free(zCmd);
+  sqlite3_free(zErr);
+  return rc;
+}
+
+int TestExpert_Init(Tcl_Interp *interp){
+  struct Cmd {
+    const char *zCmd;
+    Tcl_ObjCmdProc *xProc;
+  } aCmd[] = {
+    { "sqlite3_expert_new", test_sqlite3_expert_new },
+  };
+  int i;
+
+  for(i=0; i<sizeof(aCmd)/sizeof(struct Cmd); i++){
+    struct Cmd *p = &aCmd[i];
+    Tcl_CreateObjCommand(interp, p->zCmd, p->xProc, 0, 0);
+  }
+
+  return TCL_OK;
+}
+
+#else /* defined(SQLITE_TEST) && defined(SQLITE_ENABLE_WHEREINFO_HOOK) */
+int TestExpert_Init(Tcl_Interp *interp){
+  return TCL_OK;
+}
+#endif
diff --git a/main.mk b/main.mk
index cb41cb7e003d76c8bbf5a8c329a1114a99aea2a4..ea4f9891f7bb04ece4d9b2ad843ea32993dfdf9a 100644 (file)
--- a/main.mk
+++ b/main.mk
@@ -274,6 +274,8 @@ SRC += \
 # Source code to the test files.
 #
 TESTSRC = \
+  $(TOP)/ext/expert/sqlite3expert.c \
+  $(TOP)/ext/expert/test_expert.c \
   $(TOP)/ext/fts3/fts3_term.c \
   $(TOP)/ext/fts3/fts3_test.c \
   $(TOP)/ext/rbu/test_rbu.c \
index cfcf08aa4c06507550217fd31543b2fb1fbac393..7660557a220b30aa45ce5b2c67d8eb848863ce7a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sthe\s-file\soption\son\sthe\ssqlite3_expert\sprogram.
-D 2017-04-09T08:38:37.326
+C Changes\sto\sallow\sthe\scode\sin\ssqlite3expert.c\sto\sbe\stested\sdirectly\s(via\sthe\nAPI\sin\ssqlite3expert.h)\sinstead\sof\sby\sinvoking\sthe\ssqlite3_expert\sapplication.\nFix\smemory\sleaks\sand\sother\sproblems.
+D 2017-04-10T16:13:20.707
 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc a4c0613a18663bda56d8cf76079ab6590a7c3602e54befb4bbdef76bcaa38b6a
@@ -41,8 +41,10 @@ F ext/async/README.txt e12275968f6fde133a80e04387d0e839b0c51f91
 F ext/async/sqlite3async.c 0f3070cc3f5ede78f2b9361fb3b629ce200d7d74
 F ext/async/sqlite3async.h f489b080af7e72aec0e1ee6f1d98ab6cf2e4dcef
 F ext/expert/expert.c bf0fd71921cb7b807cda9a76fb380e3d6e6b980d6167093b2952b41ec9ad8f46
-F ext/expert/sqlite3expert.c 864ebebab5fd12cad8fb5debd26ff083dffe87ade15c1b6dcc7a7c3ae0afdd1b
+F ext/expert/expert1.test c1b1405f3ac20e9f71dacdf7bd68ff22e273b249a419260b123ebe385daf2db5 w test/expert1.test
+F ext/expert/sqlite3expert.c b87f13e90b999b5b10c4ec004b6a935150c00d3af1a16944e262172b9b831b8c
 F ext/expert/sqlite3expert.h feeaee4ab73ba52426329781bbb28032ce18cf5abd2bf6221bac2df4c32b3013
+F ext/expert/test_expert.c bad0611732d07180d586bd589cbb7713dc3ab0338c52bff29680eb2007678c05
 F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
 F ext/fts1/ft_hash.c 3927bd880e65329bdc6f506555b228b28924921b
 F ext/fts1/ft_hash.h 06df7bba40dadd19597aa400a875dbc2fed705ea
@@ -328,7 +330,7 @@ F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
-F main.mk 6d4f1f1f78a6ac453d35f18c4e696fdefbe65dfec9530a41c5579ef8ec076072
+F main.mk ef818c7b1bb21f657e3bfb363cc7167264d688ca404a666e6ddda6029e94c43b
 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -413,7 +415,7 @@ F src/sqliteInt.h 36eec0868d25b50e64a05bc7355557a0aa9bd14330c16b7d7568520b2bf2bb
 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
 F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
-F src/tclsqlite.c 6c2151b6d8d98e183a04466d40df8889c0574d79
+F src/tclsqlite.c 2e0f7f63de8329526fbcb14fa5261d3574b2a06dd330f4df680120a3e6156133
 F src/test1.c 8a98191a1da8e100f77cdb5cc716df67d405028d
 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
 F src/test3.c d03f5b5da9a2410b7a91c64b0d3306ed28ab6fee
@@ -699,7 +701,6 @@ F test/exclusive.test 9a57bd66e39144b888ca75c309914fcdefb4e3f9
 F test/exclusive2.test 984090e8e9d1b331d2e8111daf6e5d61dda0bef7
 F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
 F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
-F test/expert1.test 4108ab79ee454679e3d46e3703943ac49676b6174703a13ed81f9ee8cd794e68
 F test/expr.test 66a2c9ac34f74f036faa4092f5402c7d3162fc93
 F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
 F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
@@ -1031,7 +1032,7 @@ F test/parser1.test 391b9bf9a229547a129c61ac345ed1a6f5eb1854
 F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
 F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
-F test/permutations.test af720e7d139e7e5417341d0f0eef2b911c0b067852138dc2f5b6a451b5725118
+F test/permutations.test 9c0da2079fa37e7509957c9efbbdc282dea4ed0e732d19e6f216d53ae431a67d
 F test/pragma.test 1e94755164a3a3264cd39836de4bebcb7809e5f8
 F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
 F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
@@ -1575,7 +1576,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P e051e8f21b909c5e89a7203eef6501fecd64f82a634c4e10398b5ef7d716eb37
-R c2522cb6c6416b4473f74ba522229374
+P 0857c48e02a76490fc623364f77363165dea94ec254f93d8f0fd0bac2968c572
+R edcb3d0fdfbb918bffbc8d72b5429335
 U dan
-Z 7f4db390eaebfa3a6aedc09b4bf9a775
+Z 0d7d47356215948792ad81449f48b82b
index 53bb31e126a5422462b6a7a77b0ed458559c777a..a059662f4d02e75c2fc1896e3205801d5ba03b44 100644 (file)
@@ -1 +1 @@
-0857c48e02a76490fc623364f77363165dea94ec254f93d8f0fd0bac2968c572
\ No newline at end of file
+5dd9831721b70a89a26728adcd49c7f6103ef8266891a79c2db34d913702709e
\ No newline at end of file
index 9df023b45cc8434fa11f48aca5f18621ef646b9a..a4a0ed3f303726b34a2f2a7cbf764c756d3fc29e 100644 (file)
@@ -4129,6 +4129,7 @@ static void init_all(Tcl_Interp *interp){
 #if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK)
     extern int TestSession_Init(Tcl_Interp*);
 #endif
+    extern int TestExpert_Init(Tcl_Interp*);
     extern int Fts5tcl_Init(Tcl_Interp *);
     extern int SqliteRbu_Init(Tcl_Interp*);
     extern int Sqlitetesttcl_Init(Tcl_Interp*);
@@ -4177,6 +4178,7 @@ static void init_all(Tcl_Interp *interp){
 #if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK)
     TestSession_Init(interp);
 #endif
+    TestExpert_Init(interp);
     Fts5tcl_Init(interp);
     SqliteRbu_Init(interp);
     Sqlitetesttcl_Init(interp);
index 628e7ba44e1039dd2e3aa387f1b413b1abf5f196..7e47155154474f153e3ccf00dd4fb9bf3477495b 100644 (file)
@@ -89,6 +89,7 @@ foreach f [glob $testdir/*.test] { lappend alltests [file tail $f] }
 foreach f [glob -nocomplain       \
     $testdir/../ext/rtree/*.test  \
     $testdir/../ext/fts5/test/*.test   \
+    $testdir/../ext/expert/*.test   \
 ] { 
   lappend alltests $f 
 }