]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add an incremental optimize capability to fts5. Make the 'merge' command independent...
authordan <dan@noemail.net>
Wed, 9 Mar 2016 20:54:14 +0000 (20:54 +0000)
committerdan <dan@noemail.net>
Wed, 9 Mar 2016 20:54:14 +0000 (20:54 +0000)
FossilOrigin-Name: 556671444c03e3afca072d0f5e9bea2657de6fd3

ext/fts5/fts5Int.h
ext/fts5/fts5_config.c
ext/fts5/fts5_index.c
ext/fts5/fts5_main.c
ext/fts5/fts5_test_mi.c
ext/fts5/test/fts5_common.tcl
ext/fts5/test/fts5merge.test
ext/fts5/test/fts5optimize.test
manifest
manifest.uuid

index af4041216716cf5b42262dd6df1830aec49698e3..f9e1567fb6aef8993ff7321d6957ed40d09c76fb 100644 (file)
@@ -172,6 +172,7 @@ struct Fts5Config {
   int pgsz;                       /* Approximate page size used in %_data */
   int nAutomerge;                 /* 'automerge' setting */
   int nCrisisMerge;               /* Maximum allowed segments per level */
+  int nUsermerge;                 /* 'usermerge' setting */
   int nHashSize;                  /* Bytes of memory for in-memory hash */
   char *zRank;                    /* Name of rank function */
   char *zRankArgs;                /* Arguments to rank function */
index f49cede129cd4d1244f0747d4d6a57f686ed53d1..ccc154c3b4cc3026b77cb3c8b868ccc110f27a29 100644 (file)
@@ -18,6 +18,7 @@
 
 #define FTS5_DEFAULT_PAGE_SIZE   4050
 #define FTS5_DEFAULT_AUTOMERGE      4
+#define FTS5_DEFAULT_USERMERGE      4
 #define FTS5_DEFAULT_CRISISMERGE   16
 #define FTS5_DEFAULT_HASHSIZE    (1024*1024)
 
@@ -857,6 +858,18 @@ int sqlite3Fts5ConfigSetValue(
     }
   }
 
+  else if( 0==sqlite3_stricmp(zKey, "usermerge") ){
+    int nUsermerge = -1;
+    if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
+      nUsermerge = sqlite3_value_int(pVal);
+    }
+    if( nUsermerge<2 || nUsermerge>16 ){
+      *pbBadkey = 1;
+    }else{
+      pConfig->nUsermerge = nUsermerge;
+    }
+  }
+
   else if( 0==sqlite3_stricmp(zKey, "crisismerge") ){
     int nCrisisMerge = -1;
     if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
@@ -903,6 +916,7 @@ int sqlite3Fts5ConfigLoad(Fts5Config *pConfig, int iCookie){
   /* Set default values */
   pConfig->pgsz = FTS5_DEFAULT_PAGE_SIZE;
   pConfig->nAutomerge = FTS5_DEFAULT_AUTOMERGE;
+  pConfig->nUsermerge = FTS5_DEFAULT_USERMERGE;
   pConfig->nCrisisMerge = FTS5_DEFAULT_CRISISMERGE;
   pConfig->nHashSize = FTS5_DEFAULT_HASHSIZE;
 
index ac97a7d75f6c0a6111f451c2bac578e200ab7eb3..6f0b2d93cfb4655f195460547abac79d120ec4a0 100644 (file)
@@ -4179,13 +4179,17 @@ static void fts5IndexMergeLevel(
 
 /*
 ** Do up to nPg pages of automerge work on the index.
+**
+** Return true if any changes were actually made, or false otherwise.
 */
-static void fts5IndexMerge(
+static int fts5IndexMerge(
   Fts5Index *p,                   /* FTS5 backend object */
   Fts5Structure **ppStruct,       /* IN/OUT: Current structure of index */
-  int nPg                         /* Pages of work to do */
+  int nPg,                        /* Pages of work to do */
+  int nMin                        /* Minimum number of segments to merge */
 ){
   int nRem = nPg;
+  int bRet = 0;
   Fts5Structure *pStruct = *ppStruct;
   while( nRem>0 && p->rc==SQLITE_OK ){
     int iLvl;                   /* To iterate through levels */
@@ -4216,17 +4220,17 @@ static void fts5IndexMerge(
     }
 #endif
 
-    if( nBest<p->pConfig->nAutomerge 
-        && pStruct->aLevel[iBestLvl].nMerge==0 
-      ){
+    if( nBest<nMin && pStruct->aLevel[iBestLvl].nMerge==0 ){
       break;
     }
+    bRet = 1;
     fts5IndexMergeLevel(p, &pStruct, iBestLvl, &nRem);
     if( p->rc==SQLITE_OK && pStruct->aLevel[iBestLvl].nMerge==0 ){
       fts5StructurePromote(p, iBestLvl+1, pStruct);
     }
   }
   *ppStruct = pStruct;
+  return bRet;
 }
 
 /*
@@ -4254,7 +4258,7 @@ static void fts5IndexAutomerge(
     pStruct->nWriteCounter += nLeaf;
     nRem = (int)(p->nWorkUnit * nWork * pStruct->nLevel);
 
-    fts5IndexMerge(p, ppStruct, nRem);
+    fts5IndexMerge(p, ppStruct, nRem, p->pConfig->nAutomerge);
   }
 }
 
@@ -4474,25 +4478,38 @@ static void fts5IndexFlush(Fts5Index *p){
   }
 }
 
-
-int sqlite3Fts5IndexOptimize(Fts5Index *p){
-  Fts5Structure *pStruct;
+static Fts5Structure *fts5IndexOptimizeStruct(
+  Fts5Index *p, 
+  Fts5Structure *pStruct
+){
   Fts5Structure *pNew = 0;
-  int nSeg = 0;
-
-  assert( p->rc==SQLITE_OK );
-  fts5IndexFlush(p);
-  pStruct = fts5StructureRead(p);
+  int nByte = sizeof(Fts5Structure);
+  int nSeg = pStruct->nSegment;
+  int i;
 
-  if( pStruct ){
-    assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) );
-    nSeg = pStruct->nSegment;
-    if( nSeg>1 ){
-      int nByte = sizeof(Fts5Structure);
-      nByte += (pStruct->nLevel+1) * sizeof(Fts5StructureLevel);
-      pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte);
+  /* Figure out if this structure requires optimization. A structure does
+  ** not require optimization if either:
+  **
+  **  + it consists of fewer than two segments, or 
+  **  + all segments are on the same level, or
+  **  + all segments except one are currently inputs to a merge operation.
+  **
+  ** In the first case, return NULL. In the second, increment the ref-count
+  ** on *pStruct and return a copy of the pointer to it.
+  */
+  if( nSeg<2 ) return 0;
+  for(i=0; i<pStruct->nLevel; i++){
+    int nThis = pStruct->aLevel[i].nSeg;
+    if( nThis==nSeg || (nThis==nSeg-1 && pStruct->aLevel[i].nMerge==nThis) ){
+      fts5StructureRef(pStruct);
+      return pStruct;
     }
+    assert( pStruct->aLevel[i].nMerge<=nThis );
   }
+
+  nByte += (pStruct->nLevel+1) * sizeof(Fts5StructureLevel);
+  pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte);
+
   if( pNew ){
     Fts5StructureLevel *pLvl;
     int nByte = nSeg * sizeof(Fts5StructureSegment);
@@ -4520,8 +4537,28 @@ int sqlite3Fts5IndexOptimize(Fts5Index *p){
     }
   }
 
-  if( pNew ){
-    int iLvl = pNew->nLevel-1;
+  return pNew;
+}
+
+int sqlite3Fts5IndexOptimize(Fts5Index *p){
+  Fts5Structure *pStruct;
+  Fts5Structure *pNew = 0;
+  int nSeg = 0;
+
+  assert( p->rc==SQLITE_OK );
+  fts5IndexFlush(p);
+  pStruct = fts5StructureRead(p);
+
+  if( pStruct ){
+    pNew = fts5IndexOptimizeStruct(p, pStruct);
+  }
+  fts5StructureRelease(pStruct);
+
+  if( pNew && pNew->nSegment>0 ){
+    int iLvl;
+    for(iLvl=0; iLvl<pNew->nLevel; iLvl++){
+      if( pNew->aLevel[iLvl].nSeg ) break;
+    }
     while( p->rc==SQLITE_OK && pNew->aLevel[iLvl].nSeg>0 ){
       int nRem = FTS5_OPT_WORK_UNIT;
       fts5IndexMergeLevel(p, &pNew, iLvl, &nRem);
@@ -4531,20 +4568,31 @@ int sqlite3Fts5IndexOptimize(Fts5Index *p){
     fts5StructureRelease(pNew);
   }
 
-  fts5StructureRelease(pStruct);
   return fts5IndexReturn(p); 
 }
 
+/*
+** This is called to implement the special "VALUES('merge', $nMerge)"
+** INSERT command.
+*/
 int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){
-  Fts5Structure *pStruct;
-
-  pStruct = fts5StructureRead(p);
-  if( pStruct && pStruct->nLevel ){
-    fts5IndexMerge(p, &pStruct, nMerge);
-    fts5StructureWrite(p, pStruct);
+  Fts5Structure *pStruct = fts5StructureRead(p);
+  if( pStruct ){
+    int nMin = p->pConfig->nUsermerge;
+    if( nMerge<0 ){
+      Fts5Structure *pNew = fts5IndexOptimizeStruct(p, pStruct);
+      fts5StructureRelease(pStruct);
+      pStruct = pNew;
+      nMin = 2;
+      nMerge = nMerge*-1;
+    }
+    if( pStruct && pStruct->nLevel ){
+      if( fts5IndexMerge(p, &pStruct, nMerge, nMin) ){
+        fts5StructureWrite(p, pStruct);
+      }
+    }
+    fts5StructureRelease(pStruct);
   }
-  fts5StructureRelease(pStruct);
-
   return fts5IndexReturn(p);
 }
 
index 28f3f3e62c41f86528d15b065234f23dc556c2b3..dcd131c74adbed6959ba41a172d4fc1bddceb047 100644 (file)
@@ -1511,13 +1511,13 @@ static int fts5UpdateMethod(
       rc = SQLITE_ERROR;
     }
 
-    /* Case 1: DELETE */
+    /* DELETE */
     else if( nArg==1 ){
       i64 iDel = sqlite3_value_int64(apVal[0]);  /* Rowid to delete */
       rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0);
     }
 
-    /* Case 2: INSERT */
+    /* INSERT */
     else if( eType0!=SQLITE_INTEGER ){     
       /* If this is a REPLACE, first remove the current entry (if any) */
       if( eConflict==SQLITE_REPLACE 
@@ -1529,7 +1529,7 @@ static int fts5UpdateMethod(
       fts5StorageInsert(&rc, pTab, apVal, pRowid);
     }
 
-    /* Case 2: UPDATE */
+    /* UPDATE */
     else{
       i64 iOld = sqlite3_value_int64(apVal[0]);  /* Old rowid */
       i64 iNew = sqlite3_value_int64(apVal[1]);  /* New rowid */
index bc6d01f126d95834cd1f7f8a8658d8ff7fe85ed0..a905b85bb98966380308ed310a7ab167c3984b8d 100644 (file)
@@ -68,18 +68,22 @@ struct Fts5MatchinfoCtx {
 ** If an error occurs, return NULL and leave an error in the database 
 ** handle (accessible using sqlite3_errcode()/errmsg()).
 */
-static fts5_api *fts5_api_from_db(sqlite3 *db){
-  fts5_api *pRet = 0;
+static int fts5_api_from_db(sqlite3 *db, fts5_api **ppApi){
   sqlite3_stmt *pStmt = 0;
+  int rc;
 
-  if( SQLITE_OK==sqlite3_prepare(db, "SELECT fts5()", -1, &pStmt, 0)
-   && SQLITE_ROW==sqlite3_step(pStmt) 
-   && sizeof(pRet)==sqlite3_column_bytes(pStmt, 0)
-  ){
-    memcpy(&pRet, sqlite3_column_blob(pStmt, 0), sizeof(pRet));
+  *ppApi = 0;
+  rc = sqlite3_prepare(db, "SELECT fts5()", -1, &pStmt, 0);
+  if( rc==SQLITE_OK ){
+    if( SQLITE_ROW==sqlite3_step(pStmt) 
+        && sizeof(fts5_api*)==sqlite3_column_bytes(pStmt, 0)
+      ){
+      memcpy(ppApi, sqlite3_column_blob(pStmt, 0), sizeof(fts5_api*));
+    }
+    rc = sqlite3_finalize(pStmt);
   }
-  sqlite3_finalize(pStmt);
-  return pRet;
+
+  return rc;
 }
 
 
@@ -399,7 +403,8 @@ int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){
   /* Extract the FTS5 API pointer from the database handle. The 
   ** fts5_api_from_db() function above is copied verbatim from the 
   ** FTS5 documentation. Refer there for details. */
-  pApi = fts5_api_from_db(db);
+  rc = fts5_api_from_db(db, &pApi);
+  if( rc!=SQLITE_OK ) return rc;
 
   /* If fts5_api_from_db() returns NULL, then either FTS5 is not registered
   ** with this database handle, or an error (OOM perhaps?) has occurred.
index 32691d1c81f754b491323bc5da70ab63d6ae5eaa..0f371dcfd9d90e2e61cc3908cd05ccf157c3b83e 100644 (file)
@@ -159,6 +159,12 @@ proc fts5_aux_test_functions {db} {
   }
 }
 
+proc fts5_segcount {tbl} {
+  set N 0
+  foreach n [fts5_level_segs $tbl] { incr N $n }
+  set N
+}
+
 proc fts5_level_segs {tbl} {
   set sql "SELECT fts5_decode(rowid,block) aS r FROM ${tbl}_data WHERE rowid=10"
   set ret [list]
index 9dd1ecd026d88782610dfc9bc31db6d86a7f2ded..48e3dce933e2e0f38f92dc118179e0cfdc7e1ef8 100644 (file)
@@ -45,7 +45,7 @@ proc do_merge1_test {testname nRowPerSeg} {
     WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<$::nRowPerSeg)
       INSERT INTO x8 SELECT repeat('x y ', i % 16) FROM ii;
 
-    INSERT INTO x8(x8, rank) VALUES('automerge', 2);
+    INSERT INTO x8(x8, rank) VALUES('usermerge', 2);
   }
 
   for {set tn 1} {[lindex [fts5_level_segs x8] 0]>0} {incr tn} {
@@ -84,9 +84,9 @@ proc do_merge2_test {testname nRow} {
       execsql { INSERT INTO x8 VALUES( rnddoc(($i%16) + 5) ) }
       while {[not_merged x8]} {
         execsql {
-          INSERT INTO x8(x8, rank) VALUES('automerge', 2);
+          INSERT INTO x8(x8, rank) VALUES('usermerge', 2);
           INSERT INTO x8(x8, rank) VALUES('merge', 1);
-          INSERT INTO x8(x8, rank) VALUES('automerge', 16);
+          INSERT INTO x8(x8, rank) VALUES('usermerge', 16);
           INSERT INTO x8(x8) VALUES('integrity-check');
         }
       }
@@ -104,9 +104,9 @@ do_merge2_test 2.2   10
 do_merge2_test 2.3   20
 
 #-------------------------------------------------------------------------
-# Test that an auto-merge will complete any merge that has already been
+# Test that a merge will complete any merge that has already been
 # started, even if the number of input segments is less than the current
-# value of the 'automerge' configuration parameter.
+# value of the 'usermerge' configuration parameter.
 #
 db func rnddoc fts5_rnddoc
 
@@ -119,7 +119,7 @@ do_execsql_test 3.1 {
 }
 do_test 3.2 {
   execsql {
-    INSERT INTO x8(x8, rank) VALUES('automerge', 4);
+    INSERT INTO x8(x8, rank) VALUES('usermerge', 4);
     INSERT INTO x8(x8, rank) VALUES('merge', 1);
   }
   fts5_level_segs x8
@@ -127,14 +127,14 @@ do_test 3.2 {
 
 do_test 3.3 {
   execsql {
-    INSERT INTO x8(x8, rank) VALUES('automerge', 2);
+    INSERT INTO x8(x8, rank) VALUES('usermerge', 2);
     INSERT INTO x8(x8, rank) VALUES('merge', 1);
   }
   fts5_level_segs x8
 } {2 1}
 
 do_test 3.4 {
-  execsql { INSERT INTO x8(x8, rank) VALUES('automerge', 4) }
+  execsql { INSERT INTO x8(x8, rank) VALUES('usermerge', 4) }
   while {[not_merged x8]} {
     execsql { INSERT INTO x8(x8, rank) VALUES('merge', 1) }
   }
@@ -176,7 +176,7 @@ foreach {tn pgsz} {
       INSERT INTO x8 SELECT mydoc() FROM ii;
     WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100)
       INSERT INTO x8 SELECT mydoc() FROM ii;
-    INSERT INTO x8(x8, rank) VALUES('automerge', 2);
+    INSERT INTO x8(x8, rank) VALUES('usermerge', 2);
   }
 
   set expect [mycount]
@@ -190,5 +190,36 @@ foreach {tn pgsz} {
 #  db eval {SELECT fts5_decode(rowid, block) AS r FROM x8_data} { puts $r }
 }
 
+#-------------------------------------------------------------------------
+# Test that the 'merge' command does not modify the database if there is
+# no work to do. 
+
+do_execsql_test 5.1 {
+  CREATE VIRTUAL TABLE x9 USING fts5(one, two);
+  INSERT INTO x9(x9, rank) VALUES('pgsz', 32);
+  INSERT INTO x9(x9, rank) VALUES('automerge', 2);
+  INSERT INTO x9(x9, rank) VALUES('usermerge', 2);
+  INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
+  INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
+  INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
+  INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
+  INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
+  INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
+  INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
+  INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
+}
+
+do_test 5.2 {
+  while 1 {
+    set nChange [db total_changes]
+    execsql { INSERT INTO x9(x9, rank) VALUES('merge', 1); }
+    set nChange [expr [db total_changes] - $nChange]
+    #puts $nChange
+    if {$nChange<2} break
+  }
+} {}
+
+
+
 finish_test
 
index 984af8c532326b8a8cd57756a19f5e631e5cd208..48d4e1dd365287a4e3c14d205027ff00084a8aaa 100644 (file)
@@ -37,7 +37,6 @@ foreach {tn nStep} {
   3 50
   4 500
 } {
-if {$tn!=4} continue
   reset_db
   db func rnddoc rnddoc
   do_execsql_test 1.$tn.1 {
@@ -60,6 +59,46 @@ if {$tn!=4} continue
   do_execsql_test 1.$tn.5 {
     INSERT INTO t1(t1) VALUES('integrity-check');
   }
+
+  do_test 1.$tn.6 { fts5_segcount t1 } 1
+}
+
+foreach {tn nStep} {
+  1 2
+  2 10
+  3 50
+  4 500
+} {
+  reset_db
+  db func rnddoc rnddoc
+  do_execsql_test 1.$tn.1 {
+    CREATE VIRTUAL TABLE t1 USING fts5(x, y);
+  }
+  do_test 2.$tn.2 {
+    for {set i 0} {$i < $nStep} {incr i} {
+      execsql { INSERT INTO t1 VALUES( rnddoc(5), rnddoc(5) ) }
+    }
+  } {}
+
+  do_execsql_test 2.$tn.3 {
+    INSERT INTO t1(t1) VALUES('integrity-check');
+  }
+
+  do_test 2.$tn.4 {
+    execsql { INSERT INTO t1(t1, rank) VALUES('merge', -1) }
+    while 1 {
+      set c [db total_changes]
+      execsql { INSERT INTO t1(t1, rank) VALUES('merge', 1) }
+      set c [expr [db total_changes]-$c]
+      if {$c<2} break
+    }
+  } {}
+
+  do_execsql_test 2.$tn.5 {
+    INSERT INTO t1(t1) VALUES('integrity-check');
+  }
+
+  do_test 2.$tn.6 { fts5_segcount t1 } 1
 }
 
 finish_test
index 6d3b9274dde92cc8627140553d2b9c722824833c..590403a1e07075437753d1e47017ab80bca4efc0 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\sproblem\sin\sfts3/4\sthat\swas\scausing\sit\sto\sdiscard\sdata\scached\sin-memory\sif\san\s'optimize'\scommand\sis\srun\swhen\sthere\sis\sno\sdata\son\sdisk.\sThe\susual\sway\sthis\swould\shappen\sis\sif\sthe\svery\sfirst\stransaction\sthat\swrites\sto\sthe\sfts3/4\stable\salso\sincludes\san\s'optimize'\scommand.
-D 2016-03-09T18:17:42.821
+C Add\san\sincremental\soptimize\scapability\sto\sfts5.\sMake\sthe\s'merge'\scommand\sindependent\sof\sthe\s'automerge'\ssettings.
+D 2016-03-09T20:54:14.606
 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66
@@ -98,17 +98,17 @@ F ext/fts3/unicode/mkunicode.tcl 2debed3f582d77b3fdd0b8830880250021571fd8
 F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
 F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7
-F ext/fts5/fts5Int.h fa7c17e5c3ec9c8690387ff962f9dc6aee75e114
+F ext/fts5/fts5Int.h 59e13423371512df1992532a08fe80518244f96b
 F ext/fts5/fts5_aux.c daa57fb45216491814520bbb587e97bf81ced458
 F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd
-F ext/fts5/fts5_config.c 35c5173cae4eb17e82164a7f5aeef56a48903079
+F ext/fts5/fts5_config.c abd3ae1107ca8b8def7445a0a3b70c2e46d05986
 F ext/fts5/fts5_expr.c 8e8e4635f655133eb39018072fc0f0942a2c4337
 F ext/fts5/fts5_hash.c f3a7217c86eb8f272871be5f6aa1b6798960a337
-F ext/fts5/fts5_index.c 26a4a6112864feb599a6f6144d06a78bb179736a
-F ext/fts5/fts5_main.c db24ac714c6c4a1b3c24a1f8c25889f2952148c1
+F ext/fts5/fts5_index.c f7f3c042edf3e6a8984efa95ce1d5305d73bb535
+F ext/fts5/fts5_main.c b8501e1a6a11591c53b18ce7aea7e5386cfb0421
 F ext/fts5/fts5_storage.c f8343db90d8c95a4d4b52f6676e354b4649ffd6e
 F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966
-F ext/fts5/fts5_test_mi.c b8d04816428202b2898d4ca38deb1739ac0110ae
+F ext/fts5/fts5_test_mi.c 783b86697ebf773c18fc109992426c0173a055bc
 F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be
 F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8
 F ext/fts5/fts5_unicode2.c b450b209b157d598f7b9df9f837afb75a14c24bf
@@ -116,7 +116,7 @@ F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738
 F ext/fts5/fts5_vocab.c dba72ca393d71c2588548b51380387f6b44c77a8
 F ext/fts5/fts5parse.y 86fe6ba094a47e02fe8be2571539e6833d197764
 F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
-F ext/fts5/test/fts5_common.tcl b9b1fed811c0390511cef8b254826ea15d380f4d
+F ext/fts5/test/fts5_common.tcl b01c584144b5064f30e6c648145a2dd6bc440841
 F ext/fts5/test/fts5aa.test 7e814df4a0e6c22a6fe2d84f210fdc0b5068a084
 F ext/fts5/test/fts5ab.test 30325a89453280160106be411bba3acf138e6d1b
 F ext/fts5/test/fts5ac.test 55cad4275a1f5acabfe14d8442a8046b47e49e5f
@@ -162,11 +162,11 @@ F ext/fts5/test/fts5full.test 6f6143af0c6700501d9fd597189dfab1555bb741
 F ext/fts5/test/fts5hash.test 06f9309ccb4d5050a131594e9e47d0b21456837d
 F ext/fts5/test/fts5integrity.test f5e4f8d284385875068ad0f3e894ce43e9de835d
 F ext/fts5/test/fts5matchinfo.test f7dde99697bcb310ea8faa8eb2714d9f4dfc0e1b
-F ext/fts5/test/fts5merge.test 8f3cdba2ec9c5e7e568246e81b700ad37f764367
+F ext/fts5/test/fts5merge.test 9e04a16963e32bf7c51835ce23e58325bbdfb35f
 F ext/fts5/test/fts5merge2.test a6da3c16d694235938d1939f503cfa53f0943d75
 F ext/fts5/test/fts5near.test b214cddb1c1f1bddf45c75af768f20145f7e71cc
 F ext/fts5/test/fts5onepass.test 7ed9608e258132cb8d55e7c479b08676ad68810c
-F ext/fts5/test/fts5optimize.test 42741e7c085ee0a1276140a752d4407d97c2c9f5
+F ext/fts5/test/fts5optimize.test 0f25ce4cc1f78a4cf5dd1247d30135b3f7180a19
 F ext/fts5/test/fts5phrase.test f6d1d464da5beb25dc56277aa4f1d6102f0d9a2f
 F ext/fts5/test/fts5plan.test 6a55ecbac9890765b0e16f8c421c7e0888cfe436
 F ext/fts5/test/fts5porter.test 7cdc07bef301d70eebbfa75dcaf45c3680e1d0e1
@@ -1455,7 +1455,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 2c55c3c2950cafdc256ab540f60dc4609b9c354b
-R b4dbf73ab3865664cce5c88a4214186d
+P 79338b991bf01e81d336790ca87a0fa747da4ff3
+R a3916c8b307d01845fad235da028d539
 U dan
-Z a31e8746a8bf8afd08aed0fea525a7d3
+Z 1a31d386083951a3ddfabf8f6c0df92f
index 190da3e5edd98a1ce06c7c4773c3b360643ff09b..39d9cd0036370c6b711fa94a460e37ff85c27d2e 100644 (file)
@@ -1 +1 @@
-79338b991bf01e81d336790ca87a0fa747da4ff3
\ No newline at end of file
+556671444c03e3afca072d0f5e9bea2657de6fd3
\ No newline at end of file