]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add further tests for fts5. Fix some problems with detail=col mode and auxiliary...
authordan <dan@noemail.net>
Sat, 16 Jan 2016 18:58:51 +0000 (18:58 +0000)
committerdan <dan@noemail.net>
Sat, 16 Jan 2016 18:58:51 +0000 (18:58 +0000)
FossilOrigin-Name: de77d6026e8035c505a704e7b8cfe5af6579d35f

14 files changed:
ext/fts5/fts5_buffer.c
ext/fts5/fts5_config.c
ext/fts5/fts5_expr.c
ext/fts5/fts5_main.c
ext/fts5/fts5_tcl.c
ext/fts5/test/fts5_common.tcl
ext/fts5/test/fts5config.test
ext/fts5/test/fts5fault4.test
ext/fts5/test/fts5fault9.test [new file with mode: 0644]
ext/fts5/test/fts5hash.test
ext/fts5/test/fts5synonym.test
ext/fts5/test/fts5synonym2.test
manifest
manifest.uuid

index 251a543c5ac4609f576c8a0a725f1d1a822dd00e..8558687d8a6a39a59569f5f382658c6dd89dda0d 100644 (file)
@@ -322,14 +322,17 @@ int sqlite3Fts5TermsetAdd(
   *pbPresent = 0;
   if( p ){
     int i;
-    int hash;
+    int hash = 13;
     Fts5TermsetEntry *pEntry;
 
-    /* Calculate a hash value for this term */
-    hash = 104 + iIdx;
-    for(i=0; i<nTerm; i++){
-      hash += (hash << 3) + (int)pTerm[i];
+    /* Calculate a hash value for this term. This is the same hash checksum
+    ** used by the fts5_hash.c module. This is not important for correct
+    ** operation of the module, but is necessary to ensure that some tests
+    ** designed to produce hash table collisions really do work.  */
+    for(i=nTerm-1; i>=0; i--){
+      hash = (hash << 3) ^ hash ^ pTerm[i];
     }
+    hash = (hash << 3) ^ hash ^ iIdx;
     hash = hash % ArraySize(p->apHash);
 
     for(pEntry=p->apHash[hash]; pEntry; pEntry=pEntry->pNext){
index d9778bca20868ed9649e27b20ee1eb10fa5e899c..70b1229edbbe22c27840562ca9a6dc46c6fa34c6 100644 (file)
@@ -278,7 +278,7 @@ static int fts5ConfigParseSpecial(
         p++;
       }
 
-      if( rc==SQLITE_OK && (nPre<=0 || nPre>=1000) ){
+      if( nPre<=0 || nPre>=1000 ){
         *pzErr = sqlite3_mprintf("prefix length out of range (max 999)");
         rc = SQLITE_ERROR;
         break;
index 409fbd1d050dfd050f757bbcc20be5bfa6ed1f9b..7a433b69a0a5cf0d80abf7b7f011d04b938a762e 100644 (file)
@@ -2396,7 +2396,7 @@ int sqlite3Fts5ExprPopulatePoslists(
   }
 
   return sqlite3Fts5Tokenize(pConfig, 
-      FTS5_TOKENIZE_AUX, z, n, (void*)&sCtx, fts5ExprPopulatePoslistsCb
+      FTS5_TOKENIZE_DOCUMENT, z, n, (void*)&sCtx, fts5ExprPopulatePoslistsCb
   );
 }
 
@@ -2412,49 +2412,44 @@ static void fts5ExprClearPoslists(Fts5ExprNode *pNode){
 }
 
 static int fts5ExprCheckPoslists(Fts5ExprNode *pNode, i64 iRowid){
-  if( pNode ){
-    pNode->iRowid = iRowid;
-    pNode->bEof = 0;
-    switch( pNode->eType ){
-      case FTS5_TERM:
-      case FTS5_STRING:
-        return (pNode->pNear->apPhrase[0]->poslist.n>0);
+  pNode->iRowid = iRowid;
+  pNode->bEof = 0;
+  switch( pNode->eType ){
+    case FTS5_TERM:
+    case FTS5_STRING:
+      return (pNode->pNear->apPhrase[0]->poslist.n>0);
 
-      case FTS5_AND: {
-        int i;
-        for(i=0; i<pNode->nChild; i++){
-          if( fts5ExprCheckPoslists(pNode->apChild[i], iRowid)==0 ){
-            fts5ExprClearPoslists(pNode);
-            return 0;
-          }
+    case FTS5_AND: {
+      int i;
+      for(i=0; i<pNode->nChild; i++){
+        if( fts5ExprCheckPoslists(pNode->apChild[i], iRowid)==0 ){
+          fts5ExprClearPoslists(pNode);
+          return 0;
         }
-        break;
       }
+      break;
+    }
 
-      case FTS5_OR: {
-        int i;
-        int bRet = 0;
-        for(i=0; i<pNode->nChild; i++){
-          if( fts5ExprCheckPoslists(pNode->apChild[i], iRowid) ){
-            bRet = 1;
-          }
-        }
-        if( bRet==0 ){
-          fts5ExprClearPoslists(pNode);
+    case FTS5_OR: {
+      int i;
+      int bRet = 0;
+      for(i=0; i<pNode->nChild; i++){
+        if( fts5ExprCheckPoslists(pNode->apChild[i], iRowid) ){
+          bRet = 1;
         }
-        return bRet;
       }
+      return bRet;
+    }
 
-      default: {
-        assert( pNode->eType==FTS5_NOT );
-        if( 0==fts5ExprCheckPoslists(pNode->apChild[0], iRowid)
-         || 0!=fts5ExprCheckPoslists(pNode->apChild[1], iRowid)
+    default: {
+      assert( pNode->eType==FTS5_NOT );
+      if( 0==fts5ExprCheckPoslists(pNode->apChild[0], iRowid)
+          || 0!=fts5ExprCheckPoslists(pNode->apChild[1], iRowid)
         ){
-          fts5ExprClearPoslists(pNode);
-          return 0;
-        }
-        break;
+        fts5ExprClearPoslists(pNode);
+        return 0;
       }
+      break;
     }
   }
   return 1;
index 95fb10baeb16bb23a5efccaaf68c26b5bb7b03cc..7447f9b5e135cf3602a78c20d35ca900587b70d0 100644 (file)
@@ -844,33 +844,32 @@ static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){
 }
 
 
-static sqlite3_stmt *fts5PrepareStatement(
-  int *pRc,
+static int fts5PrepareStatement(
+  sqlite3_stmt **ppStmt,
   Fts5Config *pConfig, 
   const char *zFmt,
   ...
 ){
   sqlite3_stmt *pRet = 0;
+  int rc;
+  char *zSql;
   va_list ap;
-  va_start(ap, zFmt);
 
-  if( *pRc==SQLITE_OK ){
-    int rc;
-    char *zSql = sqlite3_vmprintf(zFmt, ap);
-    if( zSql==0 ){
-      rc = SQLITE_NOMEM; 
-    }else{
-      rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pRet, 0);
-      if( rc!=SQLITE_OK ){
-        *pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db));
-      }
-      sqlite3_free(zSql);
+  va_start(ap, zFmt);
+  zSql = sqlite3_vmprintf(zFmt, ap);
+  if( zSql==0 ){
+    rc = SQLITE_NOMEM; 
+  }else{
+    rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pRet, 0);
+    if( rc!=SQLITE_OK ){
+      *pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db));
     }
-    *pRc = rc;
+    sqlite3_free(zSql);
   }
 
   va_end(ap);
-  return pRet;
+  *ppStmt = pRet;
+  return rc;
 } 
 
 static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
@@ -878,7 +877,7 @@ static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
   Fts5Sorter *pSorter;
   int nPhrase;
   int nByte;
-  int rc = SQLITE_OK;
+  int rc;
   const char *zRank = pCsr->zRank;
   const char *zRankArgs = pCsr->zRankArgs;
   
@@ -896,7 +895,7 @@ static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
   ** table, saving it creates a circular reference.
   **
   ** If SQLite a built-in statement cache, this wouldn't be a problem. */
-  pSorter->pStmt = fts5PrepareStatement(&rc, pConfig,
+  rc = fts5PrepareStatement(&pSorter->pStmt, pConfig,
       "SELECT rowid, rank FROM %Q.%Q ORDER BY %s(%s%s%s) %s",
       pConfig->zDb, pConfig->zName, zRank, pConfig->zName,
       (zRankArgs ? ", " : ""),
@@ -2039,8 +2038,15 @@ static int fts5ApiPhraseFirstColumn(
   Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
 
   if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
+    Fts5Sorter *pSorter = pCsr->pSorter;
     int n;
-    rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, iPhrase, &pIter->a, &n);
+    if( pSorter ){
+      int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
+      n = pSorter->aIdx[iPhrase] - i1;
+      pIter->a = &pSorter->aPoslist[i1];
+    }else{
+      rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, iPhrase, &pIter->a, &n);
+    }
     if( rc==SQLITE_OK ){
       pIter->b = &pIter->a[n];
       *piCol = 0;
index e633f0ac58e61193143a5c1cfa07a6a79d4dcedd..72db65777f1d06c2853f7483183e71754195d1f8 100644 (file)
@@ -447,10 +447,12 @@ static int xF5tApi(
       zColvar = Tcl_GetString(objv[3]);
       zOffvar = Tcl_GetString(objv[4]);
 
-      for(p->pApi->xPhraseFirst(p->pFts, iPhrase, &iter, &iCol, &iOff);
-          iCol>=0;
-          p->pApi->xPhraseNext(p->pFts, &iter, &iCol, &iOff)
-      ){
+      rc = p->pApi->xPhraseFirst(p->pFts, iPhrase, &iter, &iCol, &iOff);
+      if( rc!=SQLITE_OK ){
+        Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
+        return TCL_ERROR;
+      }
+      for( ;iCol>=0; p->pApi->xPhraseNext(p->pFts, &iter, &iCol, &iOff) ){
         Tcl_SetVar2Ex(interp, zColvar, 0, Tcl_NewIntObj(iCol), 0);
         Tcl_SetVar2Ex(interp, zOffvar, 0, Tcl_NewIntObj(iOff), 0);
         rc = Tcl_EvalObjEx(interp, pScript, 0);
@@ -474,10 +476,12 @@ static int xF5tApi(
       if( Tcl_GetIntFromObj(interp, objv[2], &iPhrase) ) return TCL_ERROR;
       zColvar = Tcl_GetString(objv[3]);
 
-      for(p->pApi->xPhraseFirstColumn(p->pFts, iPhrase, &iter, &iCol);
-          iCol>=0;
-          p->pApi->xPhraseNextColumn(p->pFts, &iter, &iCol)
-      ){
+      rc = p->pApi->xPhraseFirstColumn(p->pFts, iPhrase, &iter, &iCol);
+      if( rc!=SQLITE_OK ){
+        Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
+        return TCL_ERROR;
+      }
+      for( ; iCol>=0; p->pApi->xPhraseNextColumn(p->pFts, &iter, &iCol)){
         Tcl_SetVar2Ex(interp, zColvar, 0, Tcl_NewIntObj(iCol), 0);
         rc = Tcl_EvalObjEx(interp, pScript, 0);
         if( rc==TCL_CONTINUE ) rc = TCL_OK;
index 2c7fedcefe865424835cc3e53ca01d2a5c7d8f0c..e45355a6dd00dcbb726d9d3cdcd6eeb6d788d61d 100644 (file)
@@ -510,6 +510,22 @@ proc fts5_poslist_data {expr tbl {order ASC} {aDictVar ""}} {
   set res
 }
 
+proc fts5_collist_data {expr tbl {order ASC} {aDictVar ""}} {
+  set res [list]
+
+  if {$aDictVar!=""} {
+    upvar $aDictVar aDict
+    set dict aDict
+  } else {
+    set dict ""
+  }
+
+  foreach {rowid poslist collist} [fts5_query_data $expr $tbl $order $dict] {
+    lappend res $rowid $collist
+  }
+  set res
+}
+
 #-------------------------------------------------------------------------
 #
 
@@ -561,3 +577,54 @@ proc nearset_rc {aCol args} {
   list
 }
 
+
+#-------------------------------------------------------------------------
+# Code for a simple Tcl tokenizer that supports synonyms at query time.
+#
+proc tclnum_tokenize {mode tflags text} {
+  foreach {w iStart iEnd} [fts5_tokenize_split $text] {
+    sqlite3_fts5_token $w $iStart $iEnd
+    if {$tflags == $mode && [info exists ::tclnum_syn($w)]} {
+      foreach s $::tclnum_syn($w)  { sqlite3_fts5_token -colo $s $iStart $iEnd }
+    }
+  }
+}
+
+proc tclnum_create {args} {
+  set mode query
+  if {[llength $args]} {
+    set mode [lindex $args 0]
+  }
+  if {$mode != "query" && $mode != "document"} { error "bad mode: $mode" }
+  return [list tclnum_tokenize $mode]
+}
+
+proc fts5_tclnum_register {db} {
+  foreach SYNDICT {
+    {zero  0}
+    {one   1 i}
+    {two   2 ii}
+    {three 3 iii}
+    {four  4 iv}
+    {five  5 v}
+    {six   6 vi}
+    {seven 7 vii}
+    {eight 8 viii}
+    {nine  9 ix}
+
+    {a1 a2 a3 a4 a5 a6 a7 a8 a9}
+    {b1 b2 b3 b4 b5 b6 b7 b8 b9}
+    {c1 c2 c3 c4 c5 c6 c7 c8 c9}
+  } {
+    foreach s $SYNDICT {
+      set o [list]
+      foreach x $SYNDICT {if {$x!=$s} {lappend o $x}}
+      set ::tclnum_syn($s) $o
+    }
+  }
+  sqlite3_fts5_create_tokenizer db tclnum tclnum_create
+}
+#
+# End of tokenizer code.
+#-------------------------------------------------------------------------
+
index dcda2d42a677d315908b83cf06fe28426048875b..223e504a65bda4a874aa7efe0587d880162dcca0 100644 (file)
@@ -44,6 +44,8 @@ foreach {tn opt} {
   3 {prefix='$'}
   4 {prefix='1,2,'}
   5 {prefix=',1'}
+  6 {prefix='1,2,3...'}
+  7 {prefix='1,2,3xyz'}
 } {
   set res [list 1 {malformed prefix=... directive}]
   do_catchsql_test 2.$tn "CREATE VIRTUAL TABLE f1 USING fts5(x, $opt)" $res
@@ -159,6 +161,8 @@ do_catchsql_test 8.1 {
 #   9.1.* 'pgsz' options.
 #   9.2.* 'automerge' options.
 #   9.3.* 'crisismerge' options.
+#   9.4.* a non-existant option.
+#   9.5.* 'hashsize' options.
 #
 do_execsql_test 9.0 {
   CREATE VIRTUAL TABLE abc USING fts5(a, b);
@@ -203,6 +207,16 @@ do_catchsql_test 9.4.1 {
   INSERT INTO abc(abc, rank) VALUES('nosuchoption', 1);
 } {1 {SQL logic error or missing database}}
 
+do_catchsql_test 9.5.1 {
+  INSERT INTO abc(abc, rank) VALUES('hashsize', 'not an integer');
+} {1 {SQL logic error or missing database}}
+do_catchsql_test 9.5.2 {
+  INSERT INTO abc(abc, rank) VALUES('hashsize', -500000);
+} {1 {SQL logic error or missing database}}
+do_catchsql_test 9.5.3 {
+  INSERT INTO abc(abc, rank) VALUES('hashsize', 500000);
+} {0 {}}
+
 #-------------------------------------------------------------------------
 # Too many prefix indexes. Maximum allowed is 31.
 #
@@ -214,5 +228,20 @@ foreach {tn spec} {
   do_catchsql_test 10.$tn $sql {1 {too many prefix indexes (max 31)}}
 }
 
+#-------------------------------------------------------------------------
+# errors in the detail= option.
+#
+foreach {tn opt} {
+  1 {detail=x}  
+  2 {detail='x'}
+  3 {detail='$'}
+  4 {detail='1,2,'}
+  5 {detail=',1'}
+  6 {detail=''}
+} {
+  set res [list 1 {malformed detail=... directive}]
+  do_catchsql_test 11.$tn "CREATE VIRTUAL TABLE f1 USING fts5(x, $opt)" $res
+}
+
 finish_test
 
index 989a372d496f453e4732b3a580a1abe93dca857a..acc43ebfc65a8da76455d6c460d2380de6ec74c5 100644 (file)
@@ -40,27 +40,6 @@ do_faultsim_test 1 -faults oom-* -prep {
   faultsim_test_result [list 0 {}]
 }
 
-#-------------------------------------------------------------------------
-# An OOM within an "ORDER BY rank" query.
-#
-db func rnddoc fts5_rnddoc 
-do_execsql_test 2.0 {
-  CREATE VIRTUAL TABLE xx USING fts5(x);
-  INSERT INTO xx VALUES ('abc ' || rnddoc(10));
-  INSERT INTO xx VALUES ('abc abc' || rnddoc(9));
-  INSERT INTO xx VALUES ('abc abc abc' || rnddoc(8));
-} {}
-faultsim_save_and_close
-
-do_faultsim_test 2 -faults oom-* -prep {
-  faultsim_restore_and_reopen
-  execsql { SELECT * FROM xx }
-} -body {
-  execsql { SELECT rowid FROM xx WHERE xx MATCH 'abc' ORDER BY rank }
-} -test {
-  faultsim_test_result [list 0 {3 2 1}]
-}
-
 #-------------------------------------------------------------------------
 # An OOM while "reseeking" an FTS cursor.
 #
diff --git a/ext/fts5/test/fts5fault9.test b/ext/fts5/test/fts5fault9.test
new file mode 100644 (file)
index 0000000..b827c32
--- /dev/null
@@ -0,0 +1,140 @@
+# 2015 September 3
+#
+# 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.
+#
+#*************************************************************************
+#
+# This file is focused on OOM errors.
+#
+
+source [file join [file dirname [info script]] fts5_common.tcl]
+source $testdir/malloc_common.tcl
+set testprefix fts5fault9
+
+# If SQLITE_ENABLE_FTS3 is defined, omit this file.
+ifcapable !fts5 {
+  finish_test
+  return
+}
+
+foreach_detail_mode $testprefix {
+
+fts5_aux_test_functions db
+
+if 1 {
+
+do_execsql_test 1.0 {
+  CREATE VIRTUAL TABLE t1 USING fts5(a, b, detail=%DETAIL%);
+  INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
+  WITH seq(s) AS ( SELECT 1 UNION ALL SELECT s+1 FROM seq WHERE s<50)
+  INSERT INTO t1 SELECT 'x x x y y y', 'a b c d e f' FROM seq;
+}
+
+do_faultsim_test 1 -faults oom-* -body {
+  execsql { SELECT count(*) FROM t1('x AND y') }
+} -test {
+  faultsim_test_result {0 50}
+}
+
+do_execsql_test 2.0 {
+  CREATE VIRTUAL TABLE t2 USING fts5(a, b, detail=%DETAIL%);
+  INSERT INTO t2(t2, rank) VALUES('pgsz', 32);
+  INSERT INTO t2 VALUES('abc cba', 'cba abc');
+  INSERT INTO t2 VALUES('abc cba', 'cba abc');
+  INSERT INTO t2 VALUES('abc cba', 'cba abc');
+
+  INSERT INTO t2 VALUES('axy cyx', 'cyx axy');
+  INSERT INTO t2 VALUES('axy cyx', 'cyx axy');
+  INSERT INTO t2 VALUES('axy cyx', 'cyx axy');
+}
+
+do_faultsim_test 2 -faults oom-* -body {
+  execsql { SELECT count(*) FROM t2('a* AND c*') }
+} -test {
+  faultsim_test_result {0 6}
+}
+
+
+do_execsql_test 3.0 {
+  CREATE VIRTUAL TABLE t3 USING fts5(a, detail=%DETAIL%);
+  INSERT INTO t3 VALUES('a x x a x a a a');
+  INSERT INTO t3 VALUES('x a a x a x x x');
+}
+
+do_faultsim_test 3.1 -faults oom-* -body {
+  execsql { SELECT highlight(t3, 0, '[', ']') FROM t3('a') }
+} -test {
+  faultsim_test_result {0 {{[a] x x [a] x [a] [a] [a]} {x [a] [a] x [a] x x x}}}
+}
+
+do_faultsim_test 3.2 -faults oom-t* -body {
+  execsql { SELECT fts5_test_poslist2(t3) FROM t3('x') }
+} -test {
+  faultsim_test_result \
+      {0 {{0.0.1 0.0.2 0.0.4} {0.0.0 0.0.3 0.0.5 0.0.6 0.0.7}}} \
+      {1 SQLITE_NOMEM}
+}
+
+#-------------------------------------------------------------------------
+# Test OOM injection with the xPhraseFirstColumn() API and a tokenizer
+# uses query synonyms.
+#
+fts5_tclnum_register db
+do_execsql_test 4.0 {
+  CREATE VIRTUAL TABLE t4 USING fts5(x, y, z, detail=%DETAIL%, tokenize=tclnum);
+  INSERT INTO t4 VALUES('one two three', '1 2 3', 'i ii iii');
+  INSERT INTO t4 VALUES('1 2 3', 'i ii iii', 'one two three');
+  INSERT INTO t4 VALUES('i ii iii', 'one two three', 'i ii iii');
+
+  INSERT INTO t4 VALUES('a1 a2 a3', 'a4 a5 a6', 'a7 a8 a9');
+  INSERT INTO t4 VALUES('b1 b2 b3', 'b4 b5 b6', 'b7 b8 b9');
+  INSERT INTO t4 VALUES('c1 c2 c3', 'c4 c5 c6', 'c7 c8 c9');
+}
+
+do_faultsim_test 4.1 -faults oom-t* -body {
+  execsql { SELECT rowid, fts5_test_collist(t4) FROM t4('2') }
+} -test {
+  faultsim_test_result \
+      {0 {1 {0.0 0.1 0.2} 2 {0.0 0.1 0.2} 3 {0.0 0.1 0.2}}} {1 SQLITE_NOMEM}
+}
+
+do_faultsim_test 4.2 -faults oom-t* -body {
+  execsql { SELECT rowid, fts5_test_collist(t4) FROM t4('a5 OR b5 OR c5') }
+} -test {
+  faultsim_test_result \
+      {0 {4 {0.0 0.1 0.2} 5 {1.0 1.1 1.2} 6 {2.0 2.1 2.2}}} {1 SQLITE_NOMEM}
+}
+
+}
+
+
+#-------------------------------------------------------------------------
+# An OOM within an "ORDER BY rank" query.
+#
+db func rnddoc fts5_rnddoc 
+do_execsql_test 5.0 {
+  CREATE VIRTUAL TABLE xx USING fts5(x, y, detail=%DETAIL%);
+  INSERT INTO xx VALUES ('def', 'abc ' || rnddoc(10));
+  INSERT INTO xx VALUES ('def', 'abc abc' || rnddoc(9));
+  INSERT INTO xx VALUES ('def', 'abc abc abc' || rnddoc(8));
+} {}
+faultsim_save_and_close
+
+do_faultsim_test 5 -faults oom-* -prep {
+  faultsim_restore_and_reopen
+  execsql { SELECT * FROM xx }
+} -body {
+  execsql { SELECT rowid FROM xx('abc AND def') ORDER BY rank }
+} -test {
+  faultsim_test_result [list 0 {3 2 1}]
+}
+
+} ;# foreach_detail_mode...
+
+finish_test
+
index a4a4f283430af0ecd2f503f141bfc5997bed7b4a..ac8486f070979972b3ae721ae1f87f02c58b0f8c 100644 (file)
@@ -64,11 +64,13 @@ proc random_doc {vocab nWord} {
   return $doc
 }
 
+foreach_detail_mode $testprefix {
+
 set vocab [build_vocab1]
 db func r random_doc 
 
 do_execsql_test 1.0 {
-  CREATE VIRTUAL TABLE eee USING fts5(e, ee);
+  CREATE VIRTUAL TABLE eee USING fts5(e, ee, detail=%DETAIL%);
   BEGIN;
     WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100)
     INSERT INTO eee SELECT r($vocab, 5), r($vocab, 7) FROM ii;
@@ -91,7 +93,7 @@ do_test 1.2 {
   }
 } {}
   
-do_test 1.2 {
+do_test 1.3 {
   db eval { SELECT term, doc FROM vocab } {
     set nRow [db one {SELECT count(*) FROM eee WHERE eee MATCH $term}]
     if {$nRow != $doc} {
@@ -101,10 +103,12 @@ do_test 1.2 {
   set {} {}
 } {}
 
-do_execsql_test 1.3 {
+do_execsql_test 1.4 {
   COMMIT;
   INSERT INTO eee(eee) VALUES('integrity-check');
 }
 
+} ;# foreach_detail_mode
+
 finish_test
 
index 008d2fc5439b48ae1aeb197d92fa8a0a6eacb559..185dda3ff47cd3616618e79d9abe98212ac5e3c6 100644 (file)
@@ -21,42 +21,16 @@ ifcapable !fts5 {
   return
 }
 
-foreach S {
-  {zero 0}
-  {one 1 i}
-  {two 2 ii}
-  {three 3 iii}
-  {four 4 iv}
-  {five 5 v}
-  {six 6 vi}
-  {seven 7 vii}
-  {eight 8 viii}
-  {nine 9 ix}
-} {
-  foreach s $S {
-    set o [list]
-    foreach x $S {if {$x!=$s} {lappend o $x}}
-    set ::syn($s) $o
-  }
-}
-
-proc tcl_tokenize {tflags text} {
-  foreach {w iStart iEnd} [fts5_tokenize_split $text] {
-    sqlite3_fts5_token $w $iStart $iEnd
-  }
-}
+proc tcl_create {args} { return "tcl_tokenize" }
 
-proc tcl_create {args} {
-  return "tcl_tokenize"
-}
-
-sqlite3_fts5_create_tokenizer db tcl tcl_create
+foreach_detail_mode $testprefix {
 
 #-------------------------------------------------------------------------
 # Warm body test for the code in fts5_tcl.c.
 #
+fts5_tclnum_register db
 do_execsql_test 1.0 {
-  CREATE VIRTUAL TABLE ft USING fts5(x, tokenize = tcl);
+  CREATE VIRTUAL TABLE ft USING fts5(x, tokenize = "tclnum document", detail=%DETAIL%);
   INSERT INTO ft VALUES('abc def ghi');
   INSERT INTO ft VALUES('jkl mno pqr');
   SELECT rowid, x FROM ft WHERE ft MATCH 'def';
@@ -67,22 +41,13 @@ do_execsql_test 1.0 {
 # Test a tokenizer that supports synonyms by adding extra entries to the
 # FTS index.
 #
-
-proc tcl_tokenize {tflags text} {
-  foreach {w iStart iEnd} [fts5_tokenize_split $text] {
-    sqlite3_fts5_token $w $iStart $iEnd
-    if {$tflags=="document" && [info exists ::syn($w)]} {
-      foreach s $::syn($w) {
-        sqlite3_fts5_token -colo $s $iStart $iEnd
-      }
-    }
-  }
-}
 reset_db
-sqlite3_fts5_create_tokenizer db tcl tcl_create
+fts5_tclnum_register db
 
 do_execsql_test 2.0 {
-  CREATE VIRTUAL TABLE ft USING fts5(x, tokenize = tcl);
+  CREATE VIRTUAL TABLE ft USING fts5(
+      x, tokenize = "tclnum document", detail=%DETAIL%
+  );
   INSERT INTO ft VALUES('one two three');
   INSERT INTO ft VALUES('four five six');
   INSERT INTO ft VALUES('eight nine ten');
@@ -95,6 +60,7 @@ foreach {tn expr res} {
   4 "1*" {1}
   5 "1 + 2" {1}
 } {
+  if {![fts5_expr_ok $expr ft]} continue
   do_execsql_test 2.1.$tn {
     SELECT rowid FROM ft WHERE ft MATCH $expr
   } $res
@@ -180,17 +146,7 @@ do_execsql_test 3.2.5 {
 # Check that expressions with synonyms can be parsed and executed.
 #
 reset_db
-sqlite3_fts5_create_tokenizer db tcl tcl_create
-proc tcl_tokenize {tflags text} {
-  foreach {w iStart iEnd} [fts5_tokenize_split $text] {
-    sqlite3_fts5_token $w $iStart $iEnd
-    if {$tflags=="query" && [info exists ::syn($w)]} {
-      foreach s $::syn($w) {
-        sqlite3_fts5_token -colo $s $iStart $iEnd
-      }
-    }
-  }
-}
+fts5_tclnum_register db
 
 foreach {tn expr res} {
   1  {abc}                           {"abc"}
@@ -198,11 +154,13 @@ foreach {tn expr res} {
   3  {3}                             {"3"|"iii"|"three"}
   4  {3*}                            {"3"|"iii"|"three" *}
 } {
-  do_execsql_test 4.1.$tn {SELECT fts5_expr($expr, 'tokenize=tcl')} [list $res]
+  do_execsql_test 4.1.$tn {
+    SELECT fts5_expr($expr, 'tokenize=tclnum')
+  } [list $res]
 }
 
 do_execsql_test 4.2.1 {
-  CREATE VIRTUAL TABLE xx USING fts5(x, tokenize=tcl);
+  CREATE VIRTUAL TABLE xx USING fts5(x, tokenize=tclnum, detail=%DETAIL%);
   INSERT INTO xx VALUES('one two');
   INSERT INTO xx VALUES('three four');
 }
@@ -217,7 +175,7 @@ do_execsql_test 4.2.3 {
 
 do_test 5.0 {
   execsql { 
-    CREATE VIRTUAL TABLE t1 USING fts5(a, b, tokenize=tcl)
+    CREATE VIRTUAL TABLE t1 USING fts5(a, b, tokenize=tclnum, detail=%DETAIL%)
   }
   foreach {rowid a b} {
     1 {four v 4 i three} {1 3 five five 4 one}
@@ -285,6 +243,7 @@ foreach {tn q res} {
     5 {three i v i four 4 1} {ii [five five five] iii}
   }
 } {
+  if {![fts5_expr_ok $q t1]} continue
   do_execsql_test 5.1.$tn {
     SELECT rowid, highlight(t1, 0, '[', ']'), highlight(t1, 1, '[', ']')
     FROM t1 WHERE t1 MATCH $q
@@ -316,7 +275,6 @@ foreach {tn q res} {
   } $res
 }
 
-
 #-------------------------------------------------------------------------
 # Test terms with more than 4 synonyms.
 #
@@ -334,17 +292,19 @@ proc tcl_tokenize {tflags text} {
 }
 
 do_execsql_test 6.0.1 {
-  CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize=tcl);
+  CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize=tcl, detail=%DETAIL%);
   INSERT INTO t1 VALUES('yy xx qq');
   INSERT INTO t1 VALUES('yy xx xx');
 }
-do_execsql_test 6.0.2 {
-  SELECT * FROM t1 WHERE t1 MATCH 'NEAR(y q)';
-} {{yy xx qq}}
+if {[fts5_expr_ok "NEAR(y q)" t1]} {
+  do_execsql_test 6.0.2 {
+    SELECT * FROM t1 WHERE t1 MATCH 'NEAR(y q)';
+  } {{yy xx qq}}
+}
 
 do_test 6.0.3 {
   execsql { 
-    CREATE VIRTUAL TABLE t2 USING fts5(a, b, tokenize=tcl)
+    CREATE VIRTUAL TABLE t2 USING fts5(a, b, tokenize=tcl, detail=%DETAIL%)
   }
   foreach {rowid a b} {
     1 {yyyy vvvvv qq oo yyyyyy vvvv eee} {ffff uu r qq aaaa}
@@ -387,6 +347,8 @@ foreach {tn q res} {
     2 {ww oooooo bbbbb ssssss mm} {ffffff [yy] iiii rr s ccc [qqqqq]}
   }
 } {
+  if {![fts5_expr_ok $q t2]} continue
+
   do_execsql_test 6.1.$tn.asc {
     SELECT rowid, highlight(t2, 0, '[', ']'), highlight(t2, 1, '[', ']')
     FROM t2 WHERE t2 MATCH $q
@@ -435,7 +397,7 @@ proc tcl_tokenize {tflags text} {
 }
 
 do_execsql_test 7.0.1 {
-  CREATE VIRTUAL TABLE t1 USING fts5(a, b, columnsize=1, tokenize=tcl);
+  CREATE VIRTUAL TABLE t1 USING fts5(a, b, columnsize=1, tokenize=tcl, detail=%DETAIL%);
   INSERT INTO t1 VALUES('0 2 3', '4 5 6 7');
   INSERT INTO t1 VALUES('8 9', '0 0 0 0 0 0 0 0 0 0');
   SELECT fts5_test_columnsize(t1) FROM t1 WHERE t1 MATCH '000 AND 00 AND 0';
@@ -446,7 +408,7 @@ do_execsql_test 7.0.2 {
 }
 
 do_execsql_test 7.1.1 {
-  CREATE VIRTUAL TABLE t2 USING fts5(a, b, columnsize=0, tokenize=tcl);
+  CREATE VIRTUAL TABLE t2 USING fts5(a, b, columnsize=0, tokenize=tcl, detail=%DETAIL%);
   INSERT INTO t2 VALUES('0 2 3', '4 5 6 7');
   INSERT INTO t2 VALUES('8 9', '0 0 0 0 0 0 0 0 0 0');
   SELECT fts5_test_columnsize(t2) FROM t2 WHERE t2 MATCH '000 AND 00 AND 0';
@@ -456,5 +418,7 @@ do_execsql_test 7.1.2 {
   INSERT INTO t2(t2) VALUES('integrity-check');
 }
 
+} ;# foreach_detail_mode
+
 finish_test
 
index 96cacb293f2960b71efce47f1416bdbbbe980377..dddaa17af86446669c755c7f051a24e584cea5e7 100644 (file)
@@ -21,52 +21,22 @@ ifcapable !fts5 {
   return
 }
 
-#-------------------------------------------------------------------------
-# Code for a simple Tcl tokenizer that supports synonyms at query time.
-#
-foreach SYNDICT {
-  {zero  0}
-  {one   1 i}
-  {two   2 ii}
-  {three 3 iii}
-  {four  4 iv}
-  {five  5 v}
-  {six   6 vi}
-  {seven 7 vii}
-  {eight 8 viii}
-  {nine  9 ix}
-} {
-  foreach s $SYNDICT {
-    set o [list]
-    foreach x $SYNDICT {if {$x!=$s} {lappend o $x}}
-    set ::syn($s) $o
-  }
-}
-
-proc tcl_tokenize {tflags text} {
-  foreach {w iStart iEnd} [fts5_tokenize_split $text] {
-    sqlite3_fts5_token $w $iStart $iEnd
-    if {$tflags == "query"} {
-      foreach s $::syn($w)  { sqlite3_fts5_token -colo $s $iStart $iEnd }
-    }
-  }
-}
-
-proc tcl_create {args} {
-  return "tcl_tokenize"
-}
-
-#
-# End of tokenizer code.
-#-------------------------------------------------------------------------
-
+foreach tok {query document} {
 foreach_detail_mode $testprefix {
 
-sqlite3_fts5_create_tokenizer db tcl tcl_create
+fts5_tclnum_register db
 fts5_aux_test_functions db
 
-do_execsql_test 1.0 {
-  CREATE VIRTUAL TABLE ss USING fts5(a, b, tokenize=tcl, detail=%DETAIL%);
+proc fts5_rowid {cmd} { expr [$cmd xColumnText -1] }
+sqlite3_fts5_create_function db fts5_rowid fts5_rowid
+
+do_execsql_test 1.$tok.0.1 "
+  CREATE VIRTUAL TABLE ss USING fts5(a, b, 
+       tokenize='tclnum $tok', detail=%DETAIL%);
+  INSERT INTO ss(ss, rank) VALUES('rank', 'fts5_rowid()');
+"
+
+do_execsql_test 1.$tok.0.2 {
   INSERT INTO ss VALUES('5 5 five seven 3 seven i', '2 1 5 0 two 1 i');
   INSERT INTO ss VALUES('six ix iii 7 i vii iii', 'one seven nine 4 9 1 vi');
   INSERT INTO ss VALUES('6 viii i five six zero seven', '5 v iii iv iv 3');
@@ -137,17 +107,22 @@ foreach {tn expr} {
   4.3 "NEAR(eight nine, 1) OR NEAR(six seven, 1)"
 } {
   if {[fts5_expr_ok $expr ss]==0} {
-    do_test 1.$tn.OMITTED { list } [list]
+    do_test 1.$tok.$tn.OMITTED { list } [list]
     continue
   }
 
-  set res [fts5_query_data $expr ss ASC ::syn]
-  breakpoint
-  do_execsql_test 1.$tn.[llength $res].asc {
+  set res [fts5_query_data $expr ss ASC ::tclnum_syn]
+  do_execsql_test 1.$tok.$tn.[llength $res].asc.1 {
     SELECT rowid, fts5_test_poslist(ss), fts5_test_collist(ss) FROM ss($expr)
   } $res
+
+  do_execsql_test 1.$tok.$tn.[llength $res].asc.2 {
+    SELECT rowid, fts5_test_poslist(ss), fts5_test_collist(ss) FROM ss($expr)
+    ORDER BY rank ASC
+  } $res
 }
 
+}
 }
 
 finish_test
index fa6bddb8b1978f5f7b40a17361f591413a9aa69f..8872e8fc50d52c2d6fce9f944ab28dba17c977a5 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Use\ssqlite3VdbeAddOp4()\srather\sthan\sa\sseparate\ssqlite3VdbeChangeP4()\scall,\sfor\na\sslightly\ssmaller\sand\sfaster\sbinary.
-D 2016-01-16T15:12:35.739
+C Add\sfurther\stests\sfor\sfts5.\sFix\ssome\sproblems\swith\sdetail=col\smode\sand\sauxiliary\sfunctions.
+D 2016-01-16T18:58:51.767
 F Makefile.in a476545d0c8626224d0bacac85c6e2967474af81
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc 01e855f958932d0d3ed62ec675fc63e2cef61fcb
@@ -99,14 +99,14 @@ F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
 F ext/fts5/fts5.h ff9c2782e8ed890b0de2f697a8d63971939e70c7
 F ext/fts5/fts5Int.h 313e3276ac9e0245ee722ef803253857a68722b9
 F ext/fts5/fts5_aux.c 2dafc3aee0c70d643140c77d8d70daffa51a9e9e
-F ext/fts5/fts5_buffer.c 87204c8b3b8bc62b27376eab09b74d6d5acc41f1
-F ext/fts5/fts5_config.c 9c243d04ac0ca997d2d2e2252891f2a10fbd7217
-F ext/fts5/fts5_expr.c 510db45967ca359f64f2ba2c707ab57d740cad56
+F ext/fts5/fts5_buffer.c ba59964c95f760bd5ff1dbe173b85f197a13864e
+F ext/fts5/fts5_config.c 0c384ebdd23fd055e2e50a93277b8d59da538238
+F ext/fts5/fts5_expr.c 3ba4c9588ebb2e4f852d807869af7130b6362e5a
 F ext/fts5/fts5_hash.c 1b113977296cf4212c6ec667d5e3f2bd18036955
 F ext/fts5/fts5_index.c cd036089b22b0340fccef88a3ad62ac1016c7cbb
-F ext/fts5/fts5_main.c 1d116f5c44c6f06ec282d33dd6d041c8131b3d6a
+F ext/fts5/fts5_main.c 833db0a3df10ab26e0221a9baa40cf871c450df3
 F ext/fts5/fts5_storage.c fb2eaec3aa954b680d43096dc539f8270bd6390e
-F ext/fts5/fts5_tcl.c bcacc05dec0446e7b1a44d5d906057e677bd7ea4
+F ext/fts5/fts5_tcl.c f8731e0508299bd43f1a2eff7dbeaac870768966
 F ext/fts5/fts5_test_mi.c 1ec66ffdf7632077fbd773b7a6df5153272ec070
 F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be
 F ext/fts5/fts5_tokenize.c 504984ac6993323247221eebe3cd55bead01b5f8
@@ -115,7 +115,7 @@ F ext/fts5/fts5_varint.c 3f86ce09cab152e3d45490d7586b7ed2e40c13f1
 F ext/fts5/fts5_vocab.c ee6df1a3be103414d7b7af833ae1885c7b83a9d0
 F ext/fts5/fts5parse.y 1647eba089b9b3fc058b4dc989d9da87d15b9580
 F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
-F ext/fts5/test/fts5_common.tcl 393882afb225a21edf033043bbf936951e9198c1
+F ext/fts5/test/fts5_common.tcl 75b0af04898c18df289620dd4e7442d881e3ccc1
 F ext/fts5/test/fts5aa.test 7e814df4a0e6c22a6fe2d84f210fdc0b5068a084
 F ext/fts5/test/fts5ab.test 30325a89453280160106be411bba3acf138e6d1b
 F ext/fts5/test/fts5ac.test d5073ca7bd2d9fe8aab0c82c6c75a7e4b0d70ced
@@ -134,7 +134,7 @@ F ext/fts5/test/fts5aux.test 8c687c948cc98e9a94be014df7d518acc1b3b74f
 F ext/fts5/test/fts5auxdata.test 141a7cbffcceb1bd2799b4b29c183ff8780d586e
 F ext/fts5/test/fts5bigpl.test 04ee0d7eebbebf17c31f5a0b5c5f9494eac3a0cb
 F ext/fts5/test/fts5columnsize.test a8cfef21ffa1c264b9f670a7d94eeaccb5341c07
-F ext/fts5/test/fts5config.test 42c1336cc6ed33d7e9c4a05dbce81721b765e7d0
+F ext/fts5/test/fts5config.test 83941309b94d002ed6f55d9cd814e0353c9ae013
 F ext/fts5/test/fts5conflict.test 26f4e46c4d31e16221794832a990dc4e30e18de5
 F ext/fts5/test/fts5content.test 9a952c95518a14182dc3b59e3c8fa71cda82a4e1
 F ext/fts5/test/fts5corrupt.test c2ad090192708150d50d961278df10ae7a4b8b62
@@ -148,13 +148,14 @@ F ext/fts5/test/fts5eb.test 021aa80b7ac09b964249aa32ced9ee908703e4aa
 F ext/fts5/test/fts5fault1.test 4b39c47ca3544615daa8a2f733b911fa08022c77
 F ext/fts5/test/fts5fault2.test 28c36c843bb39ae855ba79827417ecc37f114341
 F ext/fts5/test/fts5fault3.test d6e9577d4312e331a913c72931bf131704efc8f3
-F ext/fts5/test/fts5fault4.test 4864f2b5c2c083440dbe85aff60897bc1aa04603
+F ext/fts5/test/fts5fault4.test 532b6dacb963016cbf7003196bd87fb366540277
 F ext/fts5/test/fts5fault5.test 10c13a783de3f42a21e3e53e123b62ed0c3a1618
 F ext/fts5/test/fts5fault6.test 9682664d679643ac6736e90c225526cc84073cda
 F ext/fts5/test/fts5fault7.test 01be274bfc8d9bf22451a3bf5892e9399d044f1b
 F ext/fts5/test/fts5fault8.test f2d8a2b673a5f72ca1fa0e85bdbfb2041ffd347d
+F ext/fts5/test/fts5fault9.test 964a3ee82b95053bd45d809fe2b7acf4a8c90ca9
 F ext/fts5/test/fts5full.test 6f6143af0c6700501d9fd597189dfab1555bb741
-F ext/fts5/test/fts5hash.test 7cf4607b8657c383f0b520668a99971e95d8b139
+F ext/fts5/test/fts5hash.test 00668f6fa9b9bffbd7c1be29f408aa2bdade0451
 F ext/fts5/test/fts5integrity.test 87db5d4e7da0ce04a1dcba5ba91658673c997a65
 F ext/fts5/test/fts5matchinfo.test 86569026d20f1ed748236587ce798de8a96615f1
 F ext/fts5/test/fts5merge.test 8f3cdba2ec9c5e7e568246e81b700ad37f764367
@@ -173,8 +174,8 @@ F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17
 F ext/fts5/test/fts5rowid.test 400384798349d658eaf06aefa1e364957d5d4821
 F ext/fts5/test/fts5simple.test 2bc6451cbe887a9215f5b14ae307c70d850344c9
 F ext/fts5/test/fts5simple2.test 7b51f8d411e9a77fa4519fb09ba5a3afda75c94d
-F ext/fts5/test/fts5synonym.test cf88c0a56d5ea9591e3939ef1f6e294f7f2d0671
-F ext/fts5/test/fts5synonym2.test d2d9099d9d105b55ea03fd52d61ae2847d534129
+F ext/fts5/test/fts5synonym.test 6475d189c2e20d60795808f83e36bf9318708d48
+F ext/fts5/test/fts5synonym2.test eadb00c73ef0653258873e756b7e9102e0687539
 F ext/fts5/test/fts5tok1.test beb894c6f3468f10a574302f69ebe4436b0287c7
 F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
 F ext/fts5/test/fts5tokenizer.test ea4df698b35cc427ebf2ba22829d0e28386d8c89
@@ -1416,7 +1417,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 653ea15ad8e23b333e234eb5dde7b80134db2baf
-R 2155f55389b348e9a35fea6f93c01bbe
-U drh
-Z 32d5bf122f6c10496965338bc29a15a2
+P a4258cd4613c55acacb5c7b61faa3de7eb0759d2
+R 7d01724b879e1ef98656daadba5b9cfb
+U dan
+Z d745955e2f048d17831d9a126adffb23
index 39ad2ac515a6a31e4a0c967b3881e94d517417d1..94a16261bffdcb21a832ec9a07c1304a871e65dc 100644 (file)
@@ -1 +1 @@
-a4258cd4613c55acacb5c7b61faa3de7eb0759d2
\ No newline at end of file
+de77d6026e8035c505a704e7b8cfe5af6579d35f
\ No newline at end of file