]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add implementation of xInstToken() API.
authordan <Dan Kennedy>
Wed, 15 Nov 2023 11:45:19 +0000 (11:45 +0000)
committerdan <Dan Kennedy>
Wed, 15 Nov 2023 11:45:19 +0000 (11:45 +0000)
FossilOrigin-Name: a34b26fe7f60b74e7ae5cf64900920a3d352a20da2496401bcbc27041689cd07

ext/fts5/fts5Int.h
ext/fts5/fts5_expr.c
ext/fts5/fts5_index.c
ext/fts5/fts5_main.c
ext/fts5/fts5_tcl.c
ext/fts5/test/fts5origintext.test
manifest
manifest.uuid

index df25fd9ffa6477b7e5127eeaa1fb1a7fe1a5aa3c..19d9579eb7d795b7451e00d445cf145bcb01366e 100644 (file)
@@ -464,6 +464,10 @@ void *sqlite3Fts5StructureRef(Fts5Index*);
 void sqlite3Fts5StructureRelease(void*);
 int sqlite3Fts5StructureTest(Fts5Index*, void*);
 
+/*
+** Used by xInstToken() and xPhraseToken().
+*/
+int sqlite3Fts5IterToken(Fts5IndexIter*, int, int, const char**, int*);
 
 /*
 ** Insert or remove data to or from the index. Each time a document is 
@@ -774,6 +778,7 @@ int sqlite3Fts5ExprClonePhrase(Fts5Expr*, int, Fts5Expr**);
 int sqlite3Fts5ExprPhraseCollist(Fts5Expr *, int, const u8 **, int *);
 
 int sqlite3Fts5ExprQueryToken(Fts5Expr*, int, int, const char**, int*);
+int sqlite3Fts5ExprInstToken(Fts5Expr*, int, int, int, int, const char**, int*);
 
 /*******************************************
 ** The fts5_expr.c API above this point is used by the other hand-written
index 80387a90fdc56a053bcde8b9a5377fc22e1e9899..ae851a877a9eda5faa3e1b6c87db8f1087b11665 100644 (file)
@@ -3171,3 +3171,27 @@ int sqlite3Fts5ExprQueryToken(
   return SQLITE_OK;
 }
 
+int sqlite3Fts5ExprInstToken(
+  Fts5Expr *pExpr, 
+  int iPhrase, 
+  int iCol, 
+  int iOff, 
+  int iToken, 
+  const char **ppOut, 
+  int *pnOut
+){
+  Fts5ExprPhrase *pPhrase = 0;
+  Fts5IndexIter *pIter = 0;
+
+  if( iPhrase<0 || iPhrase>=pExpr->nPhrase ){
+    return SQLITE_RANGE;
+  }
+  pPhrase = pExpr->apExprPhrase[iPhrase];
+  if( iToken<0 || iToken>=pPhrase->nTerm ){
+    return SQLITE_RANGE;
+  }
+  pIter = pPhrase->aTerm[iToken].pIter;
+
+  return sqlite3Fts5IterToken(pIter, iCol, iOff+iToken, ppOut, pnOut);
+}
+
index 6cc2c139270d758fe5fefa39937baf702d042ecd..2d6d561b7b02b6bf5c2603c96ee6ba5cab9d852c 100644 (file)
@@ -323,6 +323,9 @@ typedef struct Fts5SegWriter Fts5SegWriter;
 typedef struct Fts5Structure Fts5Structure;
 typedef struct Fts5StructureLevel Fts5StructureLevel;
 typedef struct Fts5StructureSegment Fts5StructureSegment;
+typedef struct Fts5TokenMapEntry Fts5TokenMapEntry;
+typedef struct Fts5TokenMapToken Fts5TokenMapToken;
+typedef struct Fts5TokenMap Fts5TokenMap;
 
 struct Fts5Data {
   u8 *p;                          /* Pointer to buffer containing record */
@@ -605,11 +608,34 @@ struct Fts5Iter {
   int bRev;                       /* True to iterate in reverse order */
   u8 bSkipEmpty;                  /* True to skip deleted entries */
 
+  Fts5TokenMap *pTokenMap;
   i64 iSwitchRowid;               /* Firstest rowid of other than aFirst[1] */
   Fts5CResult *aFirst;            /* Current merge state (see above) */
   Fts5SegIter aSeg[1];            /* Array of segment iterators */
 };
 
+struct Fts5TokenMapEntry {
+  i64 iRowid;
+  u16 iCol;
+  int iOff;
+  int iTok;                       /* Offset into aToken[] + 1 */
+};
+
+struct Fts5TokenMapToken {
+  u8 *pTerm;
+  int nTerm;
+};
+
+struct Fts5TokenMap {
+  int nEntryAlloc;
+  int nEntry;
+  Fts5TokenMapEntry *aEntry;
+
+  int nTokenAlloc;
+  int nToken;
+  Fts5TokenMapToken *aToken;
+};
+
 
 /*
 ** An instance of the following type is used to iterate through the contents
@@ -3023,6 +3049,20 @@ static void fts5SegIterNextFrom(
   }while( p->rc==SQLITE_OK );
 }
 
+/*
+** Free the Fts5TokenMap object passed as the only argument.
+*/
+static void fts5TokenMapFree(Fts5TokenMap *pMap){
+  if( pMap ){
+    int ii;
+    for(ii=0; ii<pMap->nToken; ii++){
+      sqlite3_free(pMap->aToken[ii].pTerm);
+    }
+    sqlite3_free(pMap->aToken);
+    sqlite3_free(pMap->aEntry);
+    sqlite3_free(pMap);
+  }
+}
 
 /*
 ** Free the iterator object passed as the second argument.
@@ -3034,6 +3074,7 @@ static void fts5MultiIterFree(Fts5Iter *pIter){
       fts5SegIterClear(&pIter->aSeg[i]);
     }
     fts5BufferFree(&pIter->poslist);
+    fts5TokenMapFree(pIter->pTokenMap);
     sqlite3_free(pIter);
   }
 }
@@ -3847,6 +3888,7 @@ fts5MultiIterNew_post_check:
 static void fts5MultiIterNew2(
   Fts5Index *p,                   /* FTS5 backend to iterate within */
   Fts5Data *pData,                /* Doclist to iterate through */
+  Fts5TokenMap *pMap,             /* Token-map, if any */
   int bDesc,                      /* True for descending rowid order */
   Fts5Iter **ppOut                /* New object */
 ){
@@ -3854,7 +3896,8 @@ static void fts5MultiIterNew2(
   pNew = fts5MultiIterAlloc(p, 2);
   if( pNew ){
     Fts5SegIter *pIter = &pNew->aSeg[1];
-
+    pNew->pTokenMap = pMap;
+    pMap = 0;
     pIter->flags = FTS5_SEGITER_ONETERM;
     if( pData->szLeaf>0 ){
       pIter->pLeaf = pData;
@@ -3877,6 +3920,7 @@ static void fts5MultiIterNew2(
     *ppOut = pNew;
   }
 
+  fts5TokenMapFree(pMap);
   fts5DataRelease(pData);
 }
 
@@ -6063,6 +6107,128 @@ static void fts5MergePrefixLists(
   *p1 = out;
 }
 
+static u8 *fts5IdxBufferDup(Fts5Index *p, const u8 *pDup, int nDup){
+  u8 *pRet = fts5IdxMalloc(p, nDup+1);
+  if( pRet ){
+    memcpy(pRet, pDup, nDup);
+  }
+  return pRet;
+}
+
+static void fts5TokenMapTerm(
+  Fts5Index *p, 
+  Fts5TokenMap *pMap, 
+  const u8 *pTerm, 
+  int nTerm
+){
+  if( p->rc==SQLITE_OK ){
+    Fts5TokenMapToken *pToken = 0;
+    if( pMap->nToken==pMap->nTokenAlloc ){
+      i64 nNew = (pMap->nTokenAlloc ? pMap->nTokenAlloc * 2 : 32);
+      Fts5TokenMapToken *aNew = sqlite3_realloc64(
+          pMap->aToken, nNew*sizeof(Fts5TokenMapToken)
+      );
+      if( aNew==0 ){
+        p->rc = SQLITE_NOMEM;
+        return;
+      }
+      pMap->nTokenAlloc = nNew;
+      pMap->aToken = aNew;
+    }
+    pToken = &pMap->aToken[pMap->nToken++];
+    pToken->nTerm = nTerm;
+    pToken->pTerm = fts5IdxBufferDup(p, pTerm, nTerm);
+  }
+}
+
+
+static void fts5TokenMapPoslist(
+  Fts5Index *p, 
+  Fts5TokenMap *pMap, 
+  Fts5Iter *p1
+){
+  if( p->rc==SQLITE_OK ){
+    const u8 *a = p1->base.pData;
+    i64 iPos = 0;
+    int iOff = 0;
+
+    while( 0==sqlite3Fts5PoslistNext64(a, p1->base.nData, &iOff, &iPos) ){
+      Fts5TokenMapEntry *pEntry = 0;
+      int iCol = FTS5_POS2COLUMN(iPos);
+      int iTokOff = FTS5_POS2OFFSET(iPos);
+
+      if( pMap->nEntry==pMap->nEntryAlloc ){
+        i64 nNew = (pMap->nEntryAlloc ? pMap->nEntryAlloc * 2 : 32);
+        Fts5TokenMapEntry *aNew = sqlite3_realloc64(
+            pMap->aEntry, nNew*sizeof(Fts5TokenMapEntry)
+        );
+        if( aNew==0 ){
+          p->rc = SQLITE_NOMEM;
+          return;
+        }
+        pMap->nEntryAlloc = nNew;
+        pMap->aEntry = aNew;
+      }
+      pEntry = &pMap->aEntry[pMap->nEntry++];
+      pEntry->iRowid = p1->base.iRowid;
+      pEntry->iCol = iCol;
+      pEntry->iOff = iTokOff;
+      pEntry->iTok = pMap->nToken;
+    }
+  }
+}
+
+static int fts5TokenMapHash(i64 iRowid, int iCol, int iOff){
+  return iRowid + (iRowid << 3) + (iCol << 6) + (iOff << 9);
+}
+
+static void fts5TokenMapHashify(Fts5Index *p, Fts5TokenMap *pMap){
+  int nHash = pMap->nEntry*2;
+  Fts5TokenMapEntry *aHash = 0;
+
+  aHash = (Fts5TokenMapEntry*)fts5IdxMalloc(p, nHash*sizeof(Fts5TokenMapEntry));
+  if( aHash ){
+    int ii;
+    for(ii=0; ii<pMap->nEntry; ii++){
+      Fts5TokenMapEntry *pEntry = &pMap->aEntry[ii];
+      Fts5TokenMapEntry *pCopy = 0;
+      int iHash = fts5TokenMapHash(pEntry->iRowid, pEntry->iCol, pEntry->iOff);
+
+      while( aHash[iHash % nHash].iTok ){
+        iHash++;
+      }
+      pCopy = &aHash[iHash % nHash];
+      memcpy(pCopy, pEntry, sizeof(Fts5TokenMapEntry));
+    }
+
+    sqlite3_free(pMap->aEntry);
+    pMap->aEntry = aHash;
+    pMap->nEntry = pMap->nEntryAlloc = nHash;
+  }
+}
+
+static const u8 *fts5TokenMapLookup(
+  Fts5TokenMap *pMap,
+  i64 iRowid,
+  int iCol,
+  int iOff,
+  int *pnOut
+){
+  int iHash = fts5TokenMapHash(iRowid, iCol, iOff) % pMap->nEntry;
+  
+  for(; pMap->aEntry[iHash].iTok!=0; iHash = (iHash+1)%pMap->nEntry){
+    Fts5TokenMapEntry *pEntry = &pMap->aEntry[iHash];
+    if( pEntry->iRowid==iRowid && pEntry->iCol==iCol && pEntry->iOff==iOff ){
+      *pnOut = pMap->aToken[pEntry->iTok-1].nTerm;
+      return pMap->aToken[pEntry->iTok-1].pTerm;
+    }
+  }
+
+  *pnOut = 0;
+  return 0;
+}
+
+
 static void fts5SetupPrefixIter(
   Fts5Index *p,                   /* Index to read from */
   int bDesc,                      /* True for "ORDER BY rowid DESC" */
@@ -6077,6 +6243,7 @@ static void fts5SetupPrefixIter(
   Fts5Buffer *aBuf;
   int nBuf = 32;
   int nMerge = 1;
+  Fts5TokenMap *pMap = 0;
 
   void (*xMerge)(Fts5Index*, Fts5Buffer*, int, Fts5Buffer*);
   void (*xAppend)(Fts5Index*, u64, Fts5Iter*, Fts5Buffer*);
@@ -6094,8 +6261,12 @@ static void fts5SetupPrefixIter(
 
   aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*nBuf);
   pStruct = fts5StructureRead(p);
+  if( iIdx==0 ){
+    pMap = (Fts5TokenMap*)fts5IdxMalloc(p, sizeof(Fts5TokenMap));
+  }
+  assert( p->rc!=SQLITE_OK || (aBuf && pStruct) );
 
-  if( aBuf && pStruct ){
+  if( p->rc==SQLITE_OK ){
     const int flags = FTS5INDEX_QUERY_SCAN 
                     | FTS5INDEX_QUERY_SKIPEMPTY 
                     | FTS5INDEX_QUERY_NOOUTPUT;
@@ -6113,6 +6284,7 @@ static void fts5SetupPrefixIter(
     ** index contains all the doclists required, except for the one
     ** corresponding to the prefix itself. That one is extracted from the
     ** main term index here.  */
+    assert( iIdx==0 || pMap==0 );
     if( iIdx!=0 ){
       int dummy = 0;
       const int f2 = FTS5INDEX_QUERY_SKIPEMPTY|FTS5INDEX_QUERY_NOOUTPUT;
@@ -6145,6 +6317,13 @@ static void fts5SetupPrefixIter(
       const u8 *pTerm = pSeg->term.p;
       p1->xSetOutputs(p1, pSeg);
 
+      if( pMap ){
+        if( bNewTerm ){
+          fts5TokenMapTerm(p, pMap, &pTerm[1], nTerm-1);
+        }
+        fts5TokenMapPoslist(p, pMap, p1);
+      }
+
       assert_nc( memcmp(pToken, pTerm, MIN(nToken, nTerm))<=0 );
       if( bNewTerm ){
         if( nTerm<nToken || memcmp(pToken, pTerm, nToken) ) break;
@@ -6196,7 +6375,8 @@ static void fts5SetupPrefixIter(
       pData->p = (u8*)&pData[1];
       pData->nn = pData->szLeaf = doclist.n;
       if( doclist.n ) memcpy(pData->p, doclist.p, doclist.n);
-      fts5MultiIterNew2(p, pData, bDesc, ppIter);
+      if( pMap ) fts5TokenMapHashify(p, pMap);
+      fts5MultiIterNew2(p, pData, pMap, bDesc, ppIter);
     }
     fts5BufferFree(&doclist);
   }
@@ -6575,6 +6755,26 @@ const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIndexIter, int *pn){
   return (z ? &z[1] : 0);
 }
 
+/*
+**
+*/
+int sqlite3Fts5IterToken(
+  Fts5IndexIter *pIndexIter, 
+  int iCol, 
+  int iOff, 
+  const char **ppOut, int *pnOut
+){
+  Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
+  if( pIter->pTokenMap ){
+    *ppOut = fts5TokenMapLookup(
+        pIter->pTokenMap, pIndexIter->iRowid, iCol, iOff, pnOut
+    );
+  }else{
+    *ppOut = sqlite3Fts5IterTerm(pIndexIter, pnOut);
+  }
+  return SQLITE_OK;
+}
+
 /*
 ** Close an iterator opened by an earlier call to sqlite3Fts5IndexQuery().
 */
index 7ddc7b6fcf3dbc9e40d716361990ff0e40e5d9c0..5ef80719aed07b1bd41f5383f66efa9783293a5b 100644 (file)
@@ -2063,12 +2063,6 @@ static int fts5ApiInst(
   ){
     if( iIdx<0 || iIdx>=pCsr->nInstCount ){
       rc = SQLITE_RANGE;
-#if 0
-    }else if( fts5IsOffsetless((Fts5Table*)pCsr->base.pVtab) ){
-      *piPhrase = pCsr->aInst[iIdx*3];
-      *piCol = pCsr->aInst[iIdx*3 + 2];
-      *piOff = -1;
-#endif
     }else{
       *piPhrase = pCsr->aInst[iIdx*3];
       *piCol = pCsr->aInst[iIdx*3 + 1];
@@ -2323,6 +2317,9 @@ static int fts5ApiPhraseFirstColumn(
   return rc;
 }
 
+/*
+** xQueryToken() API implemenetation.
+*/
 static int fts5ApiQueryToken(
   Fts5Context* pCtx, 
   int iPhrase, 
@@ -2334,6 +2331,48 @@ static int fts5ApiQueryToken(
   return sqlite3Fts5ExprQueryToken(pCsr->pExpr, iPhrase, iToken, ppOut, pnOut);
 }
 
+/*
+** xInstToken() API implemenetation.
+*/
+static int fts5ApiInstToken(
+  Fts5Context *pCtx,
+  int iIdx, 
+  int iToken,
+  const char **ppOut, int *pnOut
+){
+  Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
+  int rc = SQLITE_OK;
+  if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0 
+   || SQLITE_OK==(rc = fts5CacheInstArray(pCsr)) 
+  ){
+    if( iIdx<0 || iIdx>=pCsr->nInstCount ){
+      rc = SQLITE_RANGE;
+    }else{
+      int iPhrase = pCsr->aInst[iIdx*3];
+      int iCol = pCsr->aInst[iIdx*3 + 1];
+      int iOff = pCsr->aInst[iIdx*3 + 2];
+
+      rc = sqlite3Fts5ExprInstToken(
+          pCsr->pExpr, iPhrase, iCol, iOff, iToken, ppOut, pnOut
+      );
+    }
+  }
+  return rc;
+}
+
+/*
+** xPhraseToken() API implemenetation.
+*/
+static int fts5ApiPhraseToken(
+  Fts5Context *pCtx, 
+  Fts5PhraseIter *pIter, 
+  int iToken,
+  const char **ppOut, 
+  int *pnOut
+){
+  return SQLITE_OK;
+}
+
 
 static int fts5ApiQueryPhrase(Fts5Context*, int, void*, 
     int(*)(const Fts5ExtensionApi*, Fts5Context*, void*)
@@ -2361,8 +2400,8 @@ static const Fts5ExtensionApi sFts5Api = {
   fts5ApiPhraseFirstColumn,
   fts5ApiPhraseNextColumn,
   fts5ApiQueryToken,
-  0,
-  0
+  fts5ApiInstToken,
+  fts5ApiPhraseToken
 };
 
 /*
index a9390adc9ecd464cf28dfdc829ae179458975421..853a41865e4c5dd4980184ea47e1b953b52bc651 100644 (file)
@@ -245,7 +245,8 @@ static int SQLITE_TCLAPI xF5tApi(
     { "xPhraseForeach",    4, "IPHRASE COLVAR OFFVAR SCRIPT" }, /* 16 */
     { "xPhraseColumnForeach", 3, "IPHRASE COLVAR SCRIPT" }, /* 17 */
 
-    { "xQueryToken",       2, "IPHRASE ITERM" },      /* 19 */
+    { "xQueryToken",       2, "IPHRASE ITERM" },      /* 18 */
+    { "xInstToken",        2, "IDX ITERM" },          /* 19 */
     { 0, 0, 0}
   };
 
@@ -518,6 +519,22 @@ static int SQLITE_TCLAPI xF5tApi(
       break;
     }
 
+    CASE(19, "xInstToken") {
+      const char *pTerm = 0;
+      int nTerm = 0;
+      int iIdx = 0;
+      int iTerm = 0;
+
+      if( Tcl_GetIntFromObj(interp, objv[2], &iIdx) ) return TCL_ERROR;
+      if( Tcl_GetIntFromObj(interp, objv[3], &iTerm) ) return TCL_ERROR;
+      rc = p->pApi->xInstToken(p->pFts, iIdx, iTerm, &pTerm, &nTerm);
+      if( rc==SQLITE_OK ){
+        Tcl_SetObjResult(interp, Tcl_NewStringObj(pTerm, nTerm));
+      }
+
+      break;
+    }
+
     default: 
       assert( 0 );
       break;
index 2c9a4ba5a37e2bdcdd9a179080ed795e4f5da4b5..07e5b4fb2e85d7934398c0570a1fb1fc2339b38d 100644 (file)
@@ -167,38 +167,77 @@ proc querytoken {cmd iPhrase iToken} {
 }
 sqlite3_fts5_create_function db querytoken querytoken
 
-do_execsql_test 3.0 {
+do_execsql_test 4.0 {
   CREATE VIRTUAL TABLE ft USING fts5(
       x, tokenize='origintext unicode61', tokendata=1
   );
   INSERT INTO ft VALUES('one two three four');
 }
 
-do_execsql_test 3.1 {
+do_execsql_test 4.1 {
   SELECT rowid, querytoken(ft, 0, 0) FROM ft('TwO')
 } {1 two.TwO}
-do_execsql_test 3.2 {
+do_execsql_test 4.2 {
   SELECT rowid, querytoken(ft, 0, 0) FROM ft('one TWO ThreE')
 } {1 one}
-do_execsql_test 3.3 {
+do_execsql_test 4.3 {
   SELECT rowid, querytoken(ft, 1, 0) FROM ft('one TWO ThreE')
 } {1 two.TWO}
-do_execsql_test 3.4 {
+do_execsql_test 4.4 {
   SELECT rowid, querytoken(ft, 0, 2) FROM ft('"one TWO ThreE"')
 } {1 three.ThreE}
 
-do_catchsql_test 3.5 {
+do_catchsql_test 4.5 {
   SELECT rowid, querytoken(ft, 0, 3) FROM ft('"one TWO ThreE"')
 } {1 SQLITE_RANGE}
-do_catchsql_test 3.6 {
+do_catchsql_test 4.6 {
   SELECT rowid, querytoken(ft, 1, 0) FROM ft('"one TWO ThreE"')
 } {1 SQLITE_RANGE}
-do_catchsql_test 3.7 {
+do_catchsql_test 4.7 {
   SELECT rowid, querytoken(ft, -1, 0) FROM ft('"one TWO ThreE"')
 } {1 SQLITE_RANGE}
 
+#-------------------------------------------------------------------------
+#
+reset_db
+sqlite3_fts5_register_origintext db
+proc insttoken {cmd iIdx iToken} { 
+  set txt [$cmd xInstToken $iIdx $iToken]
+  string map [list "\0" "."] $txt
+}
+sqlite3_fts5_create_function db insttoken insttoken
+fts5_aux_test_functions db
 
+do_execsql_test 5.0 {
+  CREATE VIRTUAL TABLE ft USING fts5(
+      x, tokenize='origintext unicode61', tokendata=1
+  );
+  INSERT INTO ft VALUES('one ONE One oNe oNE one');
+}
 
+do_execsql_test 5.1 {
+  SELECT insttoken(ft, 0, 0), 
+         insttoken(ft, 1, 0),
+         insttoken(ft, 2, 0),
+         insttoken(ft, 3, 0),
+         insttoken(ft, 4, 0),
+         insttoken(ft, 5, 0)
+  FROM ft('one');
+} {
+  one one.ONE one.One one.oNe one.oNE one
+}
+
+do_execsql_test 5.2 {
+  SELECT insttoken(ft, 1, 0) FROM ft('one');
+} {
+  one.ONE
+}
+
+do_execsql_test 5.3 {
+  SELECT fts5_test_poslist(ft) FROM ft('one');
+} {
+  {0.0.0 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5}
+}
 
 finish_test
 
index 4a539764cfa0388c10f9d599718569c47307a6f1..3477a07b6e990510f037d63fc2df0fad937a3263 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\snew\sfts5\sAPI\sxQueryToken().
-D 2023-11-13T14:29:12.382
+C Add\simplementation\sof\sxInstToken()\sAPI.
+D 2023-11-15T11:45:19.681
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -88,16 +88,16 @@ F ext/fts3/unicode/mkunicode.tcl d5aebf022fa4577ee8cdf27468f0d847879993959101f6d
 F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
 F ext/fts5/fts5.h e27cdb10e38d87cb041dcb56cef97addf7d902aeab07e84e7102f5fc65d3357c
-F ext/fts5/fts5Int.h 19b198459a2791415919428d44ebf4c830b59b2da6f27f8faaffe39a876b7ecf
+F ext/fts5/fts5Int.h 88ab1ee1eefa6f98e4c7fd3c96c99ef76ed2819cc3058736c87bb01e4a301628
 F ext/fts5/fts5_aux.c ee770eec0af8646db9e18fc01a0dad7345b5f5e8cbba236704cfae2d777022ad
 F ext/fts5/fts5_buffer.c 3001fbabb585d6de52947b44b455235072b741038391f830d6b729225eeaf6a5
 F ext/fts5/fts5_config.c 8072a207034b51ae9b7694121d1b5715c794e94b275e088f70ae532378ca5cdf
-F ext/fts5/fts5_expr.c 69c81af515ce1cedccf093c7c76f8b3b4f24bafbfb1d03a431af9f5c69a81834
+F ext/fts5/fts5_expr.c 4b50ed0c724cb160f086e20e964ed2d57b99d0d3c1cb1b029901c0300b11bd9f
 F ext/fts5/fts5_hash.c adda4272be401566a6e0ba1acbe70ee5cb97fce944bc2e04dc707152a0ec91b1
-F ext/fts5/fts5_index.c 145723e22ffee28dbe2a24933e74ad998d32419223c0ddb8506a1f0c39b952c4
-F ext/fts5/fts5_main.c ddac85dbd28167af81f64e568bfe9020bf9708d650de207d1465ed19938316d1
+F ext/fts5/fts5_index.c 3b51c2f0554a665694e777c8f2765cb5b1283d4bc960dde350a604af3e5e5d98
+F ext/fts5/fts5_main.c f151eb2c6d27418d907c88cd623ad4508bdcf518a79d504e850270754c228b74
 F ext/fts5/fts5_storage.c 5d10b9bdcce5b90656cad13c7d12ad4148677d4b9e3fca0481fca56d6601426d
-F ext/fts5/fts5_tcl.c 71641a0c5693c64acfad9d10e64475ec92d9f464d06ba7fd350552de373586d8
+F ext/fts5/fts5_tcl.c cf0fd0dbe64ec272491b749e0d594f563cda03336aeb60900129e6d18b0aefb8
 F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
 F ext/fts5/fts5_test_tok.c 3cb0a9b508b30d17ef025ccddd26ae3dc8ddffbe76c057616e59a9aa85d36f3b
 F ext/fts5/fts5_tokenize.c 83cfcede3898001cab84432a36ce1503e3080cf9b1c682b022ec82e267ea4c13
@@ -188,7 +188,7 @@ F ext/fts5/test/fts5onepass.test f9b7d9b2c334900c6542a869760290e2ab5382af8fbd618
 F ext/fts5/test/fts5optimize.test 36a752d24c818792032e4ff502936fc9cc5ef938721696396fdc79214b2717f1
 F ext/fts5/test/fts5optimize2.test 93e742c36b487d8874621360af5b1ce4d39b04fb9e71ce9bc34015c5fc811785
 F ext/fts5/test/fts5optimize3.test bf9c91bb927d0fb2b9a06318a217a0419183ac5913842e062c7e0b98ea5d0fca
-F ext/fts5/test/fts5origintext.test 8296984d268d1d20f85c9de316f422ffb6ebc12020d3f8a0a18144d6ca7b347f
+F ext/fts5/test/fts5origintext.test 908a1fb6b1106e4b6ed0f9cf683c2ad7f986cce1aea1e0a13b3309c6f568932b
 F ext/fts5/test/fts5phrase.test 13e5d8e9083077b3d9c74315b3c92ec723cc6eb37c8155e0bfe1bba00559f07b
 F ext/fts5/test/fts5plan.test b65cfcca9ddd6fdaa118c61e17aeec8e8433bc5b6bb307abd116514f79c49c5a
 F ext/fts5/test/fts5porter.test 8d08010c28527db66bc3feebd2b8767504aaeb9b101a986342fa7833d49d0d15
@@ -2143,8 +2143,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 b8a48cc18c94d15017f898c820fdd784efbaac20d7a45c4d97269333e8f2ec60
-R 177f59b3c48b3865f7f595e0ec855966
+P 828566392b3ea8db603cb1ae5eccbc8ac035efaa284bc7c15ba89874f634aec9
+R 7870d9470a55737470bd92d95fe480a9
 U dan
-Z ac818dc8fd8dc9007ff77eae486bea2e
+Z d10d6cf5b22c051f4553454e4a3996a4
 # Remove this line to create a well-formed Fossil manifest.
index f6858a05cd6ffd4a4014671611f80a50e78961cf..96d818fc708c4abb8d04c89cb758552bb134c982 100644 (file)
@@ -1 +1 @@
-828566392b3ea8db603cb1ae5eccbc8ac035efaa284bc7c15ba89874f634aec9
\ No newline at end of file
+a34b26fe7f60b74e7ae5cf64900920a3d352a20da2496401bcbc27041689cd07
\ No newline at end of file