]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Improve test coverage of fts5_config.c.
authordan <dan@noemail.net>
Mon, 18 May 2015 17:50:17 +0000 (17:50 +0000)
committerdan <dan@noemail.net>
Mon, 18 May 2015 17:50:17 +0000 (17:50 +0000)
FossilOrigin-Name: 47dbfadb994814c9349d4c9c113b862c2e97c01a

17 files changed:
ext/fts5/fts5.h
ext/fts5/fts5Int.h
ext/fts5/fts5_buffer.c
ext/fts5/fts5_config.c
ext/fts5/fts5_expr.c
ext/fts5/fts5_index.c
ext/fts5/fts5_vocab.c
ext/fts5/test/fts5aa.test
ext/fts5/test/fts5config.test [new file with mode: 0644]
ext/fts5/test/fts5ea.test
ext/fts5/test/fts5fault2.test
ext/fts5/test/fts5fault4.test
ext/fts5/test/fts5merge.test
ext/fts5/test/fts5near.test
ext/fts5/test/fts5vocab.test
manifest
manifest.uuid

index 28be0de676b0e1c8c86693cc9c1a3d81836fe9c2..7782bf697c62de8ffb5e3e87e992d4627282fa48 100644 (file)
@@ -203,8 +203,9 @@ struct Fts5ExtensionApi {
 **
 ** Applications may also register custom tokenizer types. A tokenizer 
 ** is registered by providing fts5 with a populated instance of the 
-** following structure. The structure methods are expected to function
-** as follows:
+** following structure. All structure methods must be defined, setting
+** any member of the fts5_tokenizer struct to NULL leads to undefined
+** behaviour. The structure methods are expected to function as follows:
 **
 ** xCreate:
 **   This function is used to allocate and inititalize a tokenizer instance.
index 3c84c9ed2adc2bddf58b0e8e8b78711ea3585130..2a66fd8b1894ca6907af4c6b198ecf72333d71cd 100644 (file)
@@ -226,6 +226,9 @@ int sqlite3Fts5PoslistNext64(
 void *sqlite3Fts5MallocZero(int *pRc, int nByte);
 char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn);
 
+/* Character set tests (like isspace(), isalpha() etc.) */
+int sqlite3Fts5IsBareword(char t);
+
 /*
 ** End of interface to code in fts5_buffer.c.
 **************************************************************************/
index dbe51fafc459244b8b1468504e13d95a2efc294a..24e7d8f65f8e23e1b63f7036be1d96393c6ebd7e 100644 (file)
@@ -264,5 +264,31 @@ char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn){
   }
   return zRet;
 }
+
+
+/*
+** Return true if character 't' may be part of an FTS5 bareword, or false
+** otherwise. Characters that may be part of barewords:
+**
+**   * All non-ASCII characters,
+**   * The 52 upper and lower case ASCII characters, and
+**   * The 10 integer ASCII characters.
+**   * The underscore character "_" (0x5F).
+*/
+int sqlite3Fts5IsBareword(char t){
+  u8 aBareword[128] = {
+    0, 0, 0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0, 0, 0,   /* 0x00 .. 0x0F */
+    0, 0, 0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0, 0, 0,   /* 0x10 .. 0x1F */
+    0, 0, 0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0, 0, 0,   /* 0x20 .. 0x2F */
+    1, 1, 1, 1, 1, 1, 1, 1,    1, 1, 0, 0, 0, 0, 0, 0,   /* 0x30 .. 0x3F */
+    0, 1, 1, 1, 1, 1, 1, 1,    1, 1, 1, 1, 1, 1, 1, 1,   /* 0x40 .. 0x4F */
+    1, 1, 1, 1, 1, 1, 1, 1,    1, 1, 1, 0, 0, 0, 0, 1,   /* 0x50 .. 0x5F */
+    0, 1, 1, 1, 1, 1, 1, 1,    1, 1, 1, 1, 1, 1, 1, 1,   /* 0x60 .. 0x6F */
+    1, 1, 1, 1, 1, 1, 1, 1,    1, 1, 1, 0, 0, 0, 0, 0    /* 0x70 .. 0x7F */
+  };
+
+  return (t & 0x80) || aBareword[(int)t];
+}
+
 #endif /* SQLITE_ENABLE_FTS5 */
 
index 90d7b7318fcaf77c255acd51cbde2365c17dc57b..4b35ac8b2c7877bd3fc5c42375ddfac5996cdece 100644 (file)
@@ -53,12 +53,7 @@ static const char *fts5ConfigSkipWhitespace(const char *pIn){
 */
 static const char *fts5ConfigSkipBareword(const char *pIn){
   const char *p = pIn;
-  while( *p      && *p!=' ' && *p!=':' && *p!='!' && *p!='@' 
-      && *p!='#' && *p!='$' && *p!='%' && *p!='^' && *p!='&' 
-      && *p!='*' && *p!='(' && *p!=')' && *p!='='
-  ){
-    p++;
-  }
+  while ( sqlite3Fts5IsBareword(*p) ) p++;
   if( p==pIn ) p = 0;
   return p;
 }
@@ -71,64 +66,62 @@ static int fts5_isdigit(char a){
 
 static const char *fts5ConfigSkipLiteral(const char *pIn){
   const char *p = pIn;
-  if( p ){
-    switch( *p ){
-      case 'n': case 'N':
-        if( sqlite3_strnicmp("null", p, 4)==0 ){
-          p = &p[4];
-        }else{
-          p = 0;
-        }
-        break;
-        
-      case 'x': case 'X':
+  switch( *p ){
+    case 'n': case 'N':
+      if( sqlite3_strnicmp("null", p, 4)==0 ){
+        p = &p[4];
+      }else{
+        p = 0;
+      }
+      break;
+
+    case 'x': case 'X':
+      p++;
+      if( *p=='\'' ){
         p++;
-        if( *p=='\'' ){
+        while( (*p>='a' && *p<='f') 
+            || (*p>='A' && *p<='F') 
+            || (*p>='0' && *p<='9') 
+            ){
+          p++;
+        }
+        if( *p=='\'' && 0==((p-pIn)%2) ){
           p++;
-          while( (*p>='a' && *p<='f') 
-              || (*p>='A' && *p<='F') 
-              || (*p>='0' && *p<='9') 
-          ){
-            p++;
-          }
-          if( *p=='\'' && 0==((p-pIn)%2) ){
-            p++;
-          }else{
-            p = 0;
-          }
         }else{
           p = 0;
         }
-        break;
+      }else{
+        p = 0;
+      }
+      break;
 
-      case '\'':
-        p++;
-        while( p ){
-          if( *p=='\'' ){
-            p++;
-            if( *p!='\'' ) break;
-          }
+    case '\'':
+      p++;
+      while( p ){
+        if( *p=='\'' ){
           p++;
-          if( *p==0 ) p = 0;
+          if( *p!='\'' ) break;
         }
-        break;
+        p++;
+        if( *p==0 ) p = 0;
+      }
+      break;
 
-      default:
-        /* maybe a number */
-        if( *p=='+' || *p=='-' ) p++;
-        while( fts5_isdigit(*p) ) p++;
+    default:
+      /* maybe a number */
+      if( *p=='+' || *p=='-' ) p++;
+      while( fts5_isdigit(*p) ) p++;
 
-        /* At this point, if the literal was an integer, the parse is 
-        ** finished. Or, if it is a floating point value, it may continue
-        ** with either a decimal point or an 'E' character. */
-        if( *p=='.' && fts5_isdigit(p[1]) ){
-          p += 2;
-          while( fts5_isdigit(*p) ) p++;
-        }
-        if( p==pIn ) p = 0;
+      /* At this point, if the literal was an integer, the parse is 
+      ** finished. Or, if it is a floating point value, it may continue
+      ** with either a decimal point or an 'E' character. */
+      if( *p=='.' && fts5_isdigit(p[1]) ){
+        p += 2;
+        while( fts5_isdigit(*p) ) p++;
+      }
+      if( p==pIn ) p = 0;
 
-        break;
-    }
+      break;
   }
 
   return p;
@@ -157,12 +150,12 @@ static int fts5Dequote(char *z){
   assert( q=='[' || q=='\'' || q=='"' || q=='`' );
   if( q=='[' ) q = ']';  
 
-  while( z[iIn] ){
+  while( ALWAYS(z[iIn]) ){
     if( z[iIn]==q ){
       if( z[iIn+1]!=q ){
         /* Character iIn was the close quote. */
-        z[iOut] = '\0';
-        return iIn+1;
+        iIn++;
+        break;
       }else{
         /* Character iIn and iIn+1 form an escaped quote character. Skip
         ** the input cursor past both and copy a single quote character 
@@ -175,9 +168,8 @@ static int fts5Dequote(char *z){
     }
   }
 
-  /* Did not find the close-quote character. Return -1. */
   z[iOut] = '\0';
-  return -1;
+  return iIn;
 }
 
 /*
@@ -270,7 +262,7 @@ static int fts5ConfigParseSpecial(
       }else{
         for(nArg=0; p && *p; nArg++){
           const char *p2 = fts5ConfigSkipWhitespace(p);
-          if( p2 && *p2=='\'' ){
+          if( *p2=='\'' ){
             p = fts5ConfigSkipLiteral(p2);
           }else{
             p = fts5ConfigSkipBareword(p2);
@@ -369,32 +361,32 @@ static const char *fts5ConfigGobbleWord(
   int *pbQuoted                   /* OUT: Set to true if dequoting required */
 ){
   const char *zRet = 0;
+
+  int nIn = strlen(zIn);
+  char *zOut = sqlite3_malloc(nIn+1);
+
+  assert( *pRc==SQLITE_OK );
   *pbQuoted = 0;
   *pzOut = 0;
 
-  if( *pRc==SQLITE_OK ){
-    int nIn = strlen(zIn);
-    char *zOut = sqlite3_malloc(nIn+1);
-
-    if( zOut==0 ){
-      *pRc = SQLITE_NOMEM;
+  if( zOut==0 ){
+    *pRc = SQLITE_NOMEM;
+  }else{
+    memcpy(zOut, zIn, nIn+1);
+    if( fts5_isopenquote(zOut[0]) ){
+      int ii = fts5Dequote(zOut);
+      zRet = &zIn[ii];
+      *pbQuoted = 1;
     }else{
-      memcpy(zOut, zIn, nIn+1);
-      if( fts5_isopenquote(zOut[0]) ){
-        int ii = fts5Dequote(zOut);
-        if( ii>0 ) zRet = &zIn[ii];
-        *pbQuoted = 1;
-      }else{
-        zRet = fts5ConfigSkipBareword(zIn);
-        zOut[zRet-zIn] = '\0';
-      }
+      zRet = fts5ConfigSkipBareword(zIn);
+      zOut[zRet-zIn] = '\0';
     }
+  }
 
-    if( zRet==0 ){
-      sqlite3_free(zOut);
-    }else{
-      *pzOut = zOut;
-    }
+  if( zRet==0 ){
+    sqlite3_free(zOut);
+  }else{
+    *pzOut = zOut;
   }
 
   return zRet;
@@ -569,7 +561,7 @@ int sqlite3Fts5ConfigParse(
 void sqlite3Fts5ConfigFree(Fts5Config *pConfig){
   if( pConfig ){
     int i;
-    if( pConfig->pTok && pConfig->pTokApi->xDelete ){
+    if( pConfig->pTok ){
       pConfig->pTokApi->xDelete(pConfig->pTok);
     }
     sqlite3_free(pConfig->zDb);
@@ -727,7 +719,7 @@ int sqlite3Fts5ConfigParseRank(
       p = fts5ConfigSkipArgs(p);
       if( p==0 ){
         rc = SQLITE_ERROR;
-      }else if( p!=pArgs ){
+      }else{
         zRankArgs = sqlite3Fts5MallocZero(&rc, 1 + p - pArgs);
         if( zRankArgs ) memcpy(zRankArgs, pArgs, p-pArgs);
       }
@@ -751,17 +743,14 @@ int sqlite3Fts5ConfigSetValue(
   int *pbBadkey
 ){
   int rc = SQLITE_OK;
-  if(      0==sqlite3_stricmp(zKey, "cookie") ){
-    pConfig->iCookie = sqlite3_value_int(pVal);
-  }
 
-  else if( 0==sqlite3_stricmp(zKey, "pgsz") ){
+  if( 0==sqlite3_stricmp(zKey, "pgsz") ){
     int pgsz = 0;
     if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
       pgsz = sqlite3_value_int(pVal);
     }
     if( pgsz<=0 || pgsz>FTS5_MAX_PAGE_SIZE ){
-      if( pbBadkey ) *pbBadkey = 1;
+      *pbBadkey = 1;
     }else{
       pConfig->pgsz = pgsz;
     }
@@ -773,7 +762,7 @@ int sqlite3Fts5ConfigSetValue(
       nAutomerge = sqlite3_value_int(pVal);
     }
     if( nAutomerge<0 || nAutomerge>64 ){
-      if( pbBadkey ) *pbBadkey = 1;
+      *pbBadkey = 1;
     }else{
       if( nAutomerge==1 ) nAutomerge = FTS5_DEFAULT_AUTOMERGE;
       pConfig->nAutomerge = nAutomerge;
@@ -786,7 +775,7 @@ int sqlite3Fts5ConfigSetValue(
       nCrisisMerge = sqlite3_value_int(pVal);
     }
     if( nCrisisMerge<0 ){
-      if( pbBadkey ) *pbBadkey = 1;
+      *pbBadkey = 1;
     }else{
       if( nCrisisMerge<=1 ) nCrisisMerge = FTS5_DEFAULT_CRISISMERGE;
       pConfig->nCrisisMerge = nCrisisMerge;
@@ -805,10 +794,10 @@ int sqlite3Fts5ConfigSetValue(
       pConfig->zRankArgs = zRankArgs;
     }else if( rc==SQLITE_ERROR ){
       rc = SQLITE_OK;
-      if( pbBadkey ) *pbBadkey = 1;
+      *pbBadkey = 1;
     }
   }else{
-    if( pbBadkey ) *pbBadkey = 1;
+    *pbBadkey = 1;
   }
   return rc;
 }
@@ -844,10 +833,11 @@ int sqlite3Fts5ConfigLoad(Fts5Config *pConfig, int iCookie){
       if( 0==sqlite3_stricmp(zK, "version") ){
         iVersion = sqlite3_value_int(pVal);
       }else{
-        sqlite3Fts5ConfigSetValue(pConfig, zK, pVal, 0);
+        int bDummy = 0;
+        sqlite3Fts5ConfigSetValue(pConfig, zK, pVal, &bDummy);
       }
     }
-    if( rc==SQLITE_OK ) rc = sqlite3_finalize(p);
+    rc = sqlite3_finalize(p);
   }
   
   if( rc==SQLITE_OK && iVersion!=FTS5_CURRENT_VERSION ){
index 3446c3e543eb5f733e0f2ec19f1a652105a9dd93..e0496fb8d27f2727df24398aec8a1da2dd28f18d 100644 (file)
@@ -117,12 +117,6 @@ static int fts5ExprIsspace(char t){
   return t==' ' || t=='\t' || t=='\n' || t=='\r';
 }
 
-static int fts5ExprIstoken(char t){
-  return fts5ExprIsspace(t)==0 && t!='\0' 
-      && t!=':' && t!='(' && t!=')' 
-      && t!=',' && t!='+' && t!='*';
-}
-
 /*
 ** Read the first token from the nul-terminated string at *pz.
 */
@@ -169,7 +163,7 @@ static int fts5ExprGetToken(
     default: {
       const char *z2;
       tok = FTS5_STRING;
-      for(z2=&z[1]; fts5ExprIstoken(*z2); z2++);
+      for(z2=&z[1]; sqlite3Fts5IsBareword(*z2); z2++);
       pToken->n = (z2 - z);
       if( pToken->n==2 && memcmp(pToken->p, "OR", 2)==0 )  tok = FTS5_OR;
       if( pToken->n==3 && memcmp(pToken->p, "NOT", 3)==0 ) tok = FTS5_NOT;
index f9317ddd66acd30c2281ffe897aea4745f2634a6..dd0f42fa3096291160055160c9b41c84ca21eff7 100644 (file)
@@ -5566,20 +5566,6 @@ static void fts5RowidFunction(
         iRowid = FTS5_SEGMENT_ROWID(segid, height, pgno);
         sqlite3_result_int64(pCtx, iRowid);
       }
-#if 0
-    }else if( 0==sqlite3_stricmp(zArg, "start-of-index") ){
-      i64 iRowid;
-      int idx;
-      if( nArg!=2 ){
-        sqlite3_result_error(pCtx, 
-            "should be: fts5_rowid('start-of-index', idx)", -1
-        );
-      }else{
-        idx = sqlite3_value_int(apVal[1]);
-        iRowid = FTS5_SEGMENT_ROWID(idx, 1, 0, 0);
-        sqlite3_result_int64(pCtx, iRowid);
-      }
-#endif
     }else {
       sqlite3_result_error(pCtx, 
         "first arg to fts5_rowid() must be 'segment' "
index ee2a316291f2002c3631c5d6c52aee8c12f48ca6..6d03877ad037bd2f8bf42df0e23ed016707dc287 100644 (file)
@@ -189,6 +189,8 @@ static int fts5VocabInitVtab(
       pRet->zFts5Db = &pRet->zFts5Tbl[nTab];
       memcpy(pRet->zFts5Tbl, zTab, nTab);
       memcpy(pRet->zFts5Db, zDb, nDb);
+      sqlite3Fts5Dequote(pRet->zFts5Tbl);
+      sqlite3Fts5Dequote(pRet->zFts5Db);
     }
   }
 
index 559a5a1256b8a4fb7cbedfc59fc56f919c1f9821..028eece68a2c498a4ed7e5d0a5b5504c1066f32f 100644 (file)
@@ -285,6 +285,9 @@ do_catchsql_test 11.1 {
 do_catchsql_test 11.2 {
   CREATE VIRTUAL TABLE rank USING fts5(a, b, c);
 } {1 {reserved fts5 table name: rank}}
+do_catchsql_test 11.3 {
+  CREATE VIRTUAL TABLE t2 USING fts5(a, b, c, rowid);
+} {1 {reserved fts5 column name: rowid}}
 
 #-------------------------------------------------------------------------
 #
@@ -377,6 +380,26 @@ do_catchsql_test 15.2 {
   INSERT INTO t1(t1) VALUES('integrity-check');
 } {1 {database disk image is malformed}}
 
+#-------------------------------------------------------------------------
+#
+do_execsql_test 16.1 {
+  CREATE VIRTUAL TABLE n1 USING fts5(a);
+  INSERT INTO n1 VALUES('a b c d');
+}
+
+proc funk {} {
+  set fd [db incrblob main n1_data block 10]
+  fconfigure $fd -encoding binary -translation binary
+  puts -nonewline $fd "\x44\x45"
+  close $fd
+  db eval { UPDATE n1_config SET v=50 WHERE k='version' }
+}
+db func funk funk
+
+do_catchsql_test 16.2 {
+  SELECT funk(), bm25(n1), funk() FROM n1 WHERE n1 MATCH 'a+b+c+d'
+} {1 {SQL logic error or missing database}}
+
 finish_test
 
 
diff --git a/ext/fts5/test/fts5config.test b/ext/fts5/test/fts5config.test
new file mode 100644 (file)
index 0000000..22e7631
--- /dev/null
@@ -0,0 +1,202 @@
+# 2015 Jan 13
+#
+# 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 focuses on the code in fts5_config.c, which is largely concerned
+# with parsing the various configuration and CREATE TABLE options.
+#
+
+source [file join [file dirname [info script]] fts5_common.tcl]
+set testprefix fts5config
+
+#-------------------------------------------------------------------------
+# Try different types of quote characters.
+#
+do_execsql_test 1.0 {
+  CREATE VIRTUAL TABLE t1 USING fts5('a', "b", [c], `d`);
+  PRAGMA table_info = t1;
+} {
+  0 a {} 0 {} 0 
+  1 b {} 0 {} 0 
+  2 c {} 0 {} 0 
+  3 d {} 0 {} 0
+}
+
+#-------------------------------------------------------------------------
+# Syntax errors in the prefix= option.
+#
+foreach {tn opt} {
+  1 {prefix=x}  
+  2 {prefix='x'}
+  3 {prefix='$'}
+} {
+  set res [list 1 {malformed prefix=... directive}]
+  do_catchsql_test 2.$tn "CREATE VIRTUAL TABLE f1 USING fts5(x, $opt)" $res
+}
+
+#-------------------------------------------------------------------------
+# Syntax errors in the 'rank' option.
+#
+foreach {tn val} {
+  1 "f1(xyz)"
+  2 "f1(zyx)"
+  3 "f1(nzz)"
+  4 "f1(x'!!')"
+  5 "f1(x':;')"
+  6 "f1(x'[]')"
+  7 "f1(x'{}')"
+  8 "f1('abc)"
+} {
+  do_catchsql_test 3.$tn {
+    INSERT INTO t1(t1, rank) VALUES('rank', $val);
+  } {1 {SQL logic error or missing database}}
+}
+
+#-------------------------------------------------------------------------
+# The parsing of SQL literals specified as part of 'rank' options.
+#
+do_execsql_test 4.0 {
+  CREATE VIRTUAL TABLE zzz USING fts5(one);
+  INSERT INTO zzz VALUES('a b c');
+}
+proc first {cmd A} { return $A }
+sqlite3_fts5_create_function db first first
+
+foreach {tn arg} {
+  1 "123"
+  2 "'01234567890ABCDEF'"
+  3 "x'0123'"
+  4 "x'ABCD'"
+  5 "x'0123456789ABCDEF'"
+  6 "x'0123456789abcdef'"
+  7 "22.5"
+  8 "-91.5"
+  9 "-.5"
+  10 "''''"
+  11 "+.5"
+} {
+  set func [string map {' ''} "first($arg)"]
+  do_execsql_test 4.1.$tn "
+    INSERT INTO zzz(zzz, rank) VALUES('rank', '$func');
+    SELECT rank IS $arg FROM zzz WHERE zzz MATCH 'a + b + c'
+  " 1
+}
+
+do_execsql_test 4.2 {
+  INSERT INTO zzz(zzz, rank) VALUES('rank', 'f1()');
+} {}
+
+#-------------------------------------------------------------------------
+# Misquoting in tokenize= and other options. 
+#
+do_catchsql_test 5.1 {
+  CREATE VIRTUAL TABLE xx USING fts5(x, tokenize="porter 'ascii");
+} {1 {parse error in tokenize directive}} 
+
+breakpoint
+do_catchsql_test 5.2 {
+  CREATE VIRTUAL TABLE xx USING fts5(x, [y[]);
+} {0 {}}
+
+do_catchsql_test 5.3 {
+  CREATE VIRTUAL TABLE yy USING fts5(x, [y]]);
+} {1 {unrecognized token: "]"}}
+
+#-------------------------------------------------------------------------
+# Errors in prefix= directives.
+#
+do_catchsql_test 6.1 {
+  CREATE VIRTUAL TABLE abc USING fts5(a, prefix=1, prefix=2);
+} {1 {multiple prefix=... directives}}
+do_catchsql_test 6.2 {
+  CREATE VIRTUAL TABLE abc USING fts5(a, prefix='1, 2, 1001');
+} {1 {prefix length out of range: 1001}}
+do_catchsql_test 6.3 {
+  CREATE VIRTUAL TAbLE abc USING fts5(a, prefix='1, 2, 0000');
+} {1 {prefix length out of range: 0}}
+do_catchsql_test 6.4 {
+  CREATE VIRTUAL TABLE abc USING fts5(a, prefix='1  , 1000000');
+} {1 {malformed prefix=... directive}}
+
+#-------------------------------------------------------------------------
+# Duplicate tokenize= and other options.
+#
+do_catchsql_test 7.1 {
+  CREATE VIRTUAL TABLE abc USING fts5(a, tokenize=porter, tokenize=ascii);
+} {1 {multiple tokenize=... directives}}
+do_catchsql_test 7.2 {
+  CREATE VIRTUAL TABLE abc USING fts5(a, content=porter, content=ascii);
+} {1 {multiple content=... directives}}
+do_catchsql_test 7.3 {
+  CREATE VIRTUAL TABLE abc USING fts5(a, content_rowid=porter, content_rowid=a);
+} {1 {multiple content_rowid=... directives}}
+
+#-------------------------------------------------------------------------
+# Unrecognized option.
+#
+do_catchsql_test 8.0 {
+  CREATE VIRTUAL TABLE abc USING fts5(a, nosuchoption=123);
+} {1 {unrecognized option: "nosuchoption"}}
+do_catchsql_test 8.1 {
+  CREATE VIRTUAL TABLE abc USING fts5(a, "nosuchoption"=123);
+} {1 {parse error in ""nosuchoption"=123"}}
+
+#-------------------------------------------------------------------------
+# Errors in:
+#
+#   9.1.* 'pgsz' options.
+#   9.2.* 'automerge' options.
+#   9.3.* 'crisismerge' options.
+#
+do_execsql_test 9.0 {
+  CREATE VIRTUAL TABLE abc USING fts5(a, b);
+} {}
+do_catchsql_test 9.1.1 {
+  INSERT INTO abc(abc, rank) VALUES('pgsz', -5);
+} {1 {SQL logic error or missing database}}
+do_catchsql_test 9.1.2 {
+  INSERT INTO abc(abc, rank) VALUES('pgsz', 50000000);
+} {1 {SQL logic error or missing database}}
+do_catchsql_test 9.1.3 {
+  INSERT INTO abc(abc, rank) VALUES('pgsz', 66.67);
+} {1 {SQL logic error or missing database}}
+
+do_catchsql_test 9.2.1 {
+  INSERT INTO abc(abc, rank) VALUES('automerge', -5);
+} {1 {SQL logic error or missing database}}
+do_catchsql_test 9.2.2 {
+  INSERT INTO abc(abc, rank) VALUES('automerge', 50000000);
+} {1 {SQL logic error or missing database}}
+do_catchsql_test 9.2.3 {
+  INSERT INTO abc(abc, rank) VALUES('automerge', 66.67);
+} {1 {SQL logic error or missing database}}
+do_execsql_test 9.2.4 {
+  INSERT INTO abc(abc, rank) VALUES('automerge', 1);
+} {}
+
+do_catchsql_test 9.3.1 {
+  INSERT INTO abc(abc, rank) VALUES('crisismerge', -5);
+} {1 {SQL logic error or missing database}}
+do_catchsql_test 9.3.2 {
+  INSERT INTO abc(abc, rank) VALUES('crisismerge', 66.67);
+} {1 {SQL logic error or missing database}}
+do_execsql_test 9.3.3 {
+  INSERT INTO abc(abc, rank) VALUES('crisismerge', 1);
+} {}
+do_execsql_test 9.3.4 {
+  INSERT INTO abc(abc, rank) VALUES('crisismerge', 50000000);
+} {}
+
+do_catchsql_test 9.4.1 {
+  INSERT INTO abc(abc, rank) VALUES('nosuchoption', 1);
+} {1 {SQL logic error or missing database}}
+
+finish_test
+
index b80e767b634e1907831858620b4053ec19cd2a26..3929ed9f594944db0fe6badacbcadb521f865ec0 100644 (file)
@@ -74,7 +74,7 @@ foreach {tn expr err} {
   11 {a AND "abc}                  {unterminated string}
 
   12 {NEAR(a b, xyz)}              {expected integer, got "xyz"}
-  13 {NEAR(a b, // )}              {expected integer, got "//"}
+  13 {NEAR(a b, // )}              {fts5: syntax error near "/"}
 } {
   do_catchsql_test 3.$tn {SELECT fts5_expr($expr, 'name', 'addr')} [list 1 $err]
 }
index 9bf9b85e2b8bc67f6a5e4646bc957e0ed58375ce..ef1df8826ab4dfb483c44c741de83f9958af1bdc 100644 (file)
@@ -117,5 +117,24 @@ do_faultsim_test 4.1 -faults oom-trans* -prep {
   faultsim_test_result {0 {}}
 }
 
+#-------------------------------------------------------------------------
+# OOM while parsing a tokenize=option
+#
+reset_db
+faultsim_save_and_close
+do_faultsim_test 5.0 -faults oom-* -prep {
+  faultsim_restore_and_reopen
+} -body {
+  execsql { 
+    CREATE VIRTUAL TABLE uio USING fts5(a, b, 
+      tokenize="porter 'ascii'",
+      content="another table",
+      content_rowid="somecolumn"
+    );
+  }
+} -test {
+  faultsim_test_result {0 {}}
+}
+
 finish_test
 
index b22407c5cbdb79fa3259abf34cfb728d39d18509..f160a84ba354d0e6b39c156fc0aa98fbb7ebebe2 100644 (file)
@@ -326,6 +326,20 @@ do_faultsim_test 10.3 -faults oom-t* -body {
   faultsim_test_result {0 {x : "a"}}
 }
 
+#-------------------------------------------------------------------------
+# OOM while configuring 'rank' option.
+#
+reset_db
+do_execsql_test 11.0 {
+  CREATE VIRTUAL TABLE ft USING fts5(x);
+}
+do_faultsim_test 11.1 -faults oom-* -body {
+  db eval { 
+    INSERT INTO ft(ft, rank) VALUES('rank', 'bm25(10.0, 5.0)');
+  }
+} -test {
+  faultsim_test_result {0 {}}
+}
 
 finish_test
 
index d869c6cedbda393289d951a85f3741732554d6c3..023a2f7fe876113b1cb2367f3c301e5ab9600259 100644 (file)
@@ -181,7 +181,7 @@ foreach {tn pgsz} {
       } $expect
       break
     }
-  db eval {SELECT fts5_decode(rowid, block) AS r FROM x8_data} { puts $r }
+#  db eval {SELECT fts5_decode(rowid, block) AS r FROM x8_data} { puts $r }
 }
 
 finish_test
index f545447e6f7c1c207747562c29e1f4220736f15d..dffce294315d11fa5602259ab9b3cfe015c022fd 100644 (file)
@@ -24,7 +24,7 @@ proc do_near_test {tn doc near res} {
 }
 
 execsql { 
-  CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize = 'ascii tokenchars .'
+  CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize = "ascii tokenchars '.'"
 }
 
 do_near_test 1.1 ". . a . . . b . ." { NEAR(a b, 5) } 1
index b61db67d7bbe2d8052a22f695acd229f127fd4bc..fcef2b793dbf4857a6e018cfea1f844dd3a911af 100644 (file)
@@ -82,9 +82,9 @@ do_execsql_test 2.0 {
   INSERT INTO tt VALUES('g d e f d e', 'a c d b a g');
   INSERT INTO tt VALUES('e f a c c b', 'b f e a f d y');
   INSERT INTO tt VALUES('c c a a c f', 'd g a e b g');
-  CREATE VIRTUAL TABLE tv USING fts5vocab(tt, 'col');
-  SELECT * FROM tv;
-} {
+}
+
+set res_col {
   a 0 6 11    a 1 7 9
   b 0 6 7     b 1 7 7 
   c 0 6 12    c 1 5 8 
@@ -94,16 +94,31 @@ do_execsql_test 2.0 {
   g 0 5 7     g 1 5 7
   x 0 1 1     y 1 1 1
 }
-
-do_execsql_test 2.1 {
-  CREATE VIRTUAL TABLE temp.tv2 USING fts5vocab(main, tt, 'row');
-  SELECT * FROM tv2;
-} {
+set res_row {
   a 10 20   b 9 14   c 9 20   d 9 19   
   e 8 13   f 10 20   g 7 14   x 1 1   
   y 1 1
 }
 
+foreach {tn tbl resname} {
+  1 "fts5vocab(tt, 'col')" res_col
+  2 "fts5vocab(tt, 'row')" res_row
+  3 "fts5vocab(tt, \"row\")" res_row
+  4 "fts5vocab(tt, [row])" res_row
+  5 "fts5vocab(tt, `row`)" res_row
+
+  6 "fts5vocab('tt', 'row')" res_row
+  7 "fts5vocab(\"tt\", \"row\")" res_row
+  8 "fts5vocab([tt], [row])" res_row
+  9 "fts5vocab(`tt`, `row`)" res_row
+} {
+  do_execsql_test 2.$tn "
+    DROP TABLE IF EXISTS tv;
+    CREATE VIRTUAL TABLE tv USING $tbl;
+    SELECT * FROM tv;
+  " [set $resname]
+}
+
 #-------------------------------------------------------------------------
 #
 foreach {tn sql} {
index a0e7897b838dbae1e349ae49d4a212ff0c990db6..4488ddf4f5b25edc84c3f81158d9501277dca366 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Further\stest\scoverage\simprovements\sfor\sfts5.
-D 2015-05-16T20:04:43.177
+C Improve\stest\scoverage\sof\sfts5_config.c.
+D 2015-05-18T17:50:17.248
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in edfc69769e613a6359c42c06ea1d42c3bece1736
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -105,23 +105,23 @@ F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
 F ext/fts3/unicode/mkunicode.tcl 159c1194da0bc72f51b3c2eb71022568006dc5ad
 F ext/fts5/extract_api_docs.tcl 55a6d648d516f35d9a1e580ac00de27154e1904a
 F ext/fts5/fts5.c 74d18b4dc7518c7cd85609f1541e83bc564619a2
-F ext/fts5/fts5.h 24a2cc35b5e76eec57b37ba48c12d9d2cb522b3a
-F ext/fts5/fts5Int.h e01aec94c0d927924134c30afd9803425cd88812
+F ext/fts5/fts5.h 4266c6231094005b051dbfc8dd85d2bc57243d34
+F ext/fts5/fts5Int.h 9e581dc077d4c6758eaeb0d6a85dc875f53918dc
 F ext/fts5/fts5_aux.c d53f00f31ad615ca4f139dd8751f9041afa00971
-F ext/fts5/fts5_buffer.c 70b971e13503566f1e257941c60817ba0920a16b
-F ext/fts5/fts5_config.c 05811f0bd80c396afcf3ceea68da16149a9a3258
-F ext/fts5/fts5_expr.c a88af159ce5dcc44d7262ea80865ffc8e4ab2143
+F ext/fts5/fts5_buffer.c 861599a0abe2383f0cd0352c57001140a26b0930
+F ext/fts5/fts5_config.c 11f969ed711a0a8b611d47431d74c372ad78c713
+F ext/fts5/fts5_expr.c 0c4b50bb48740c76b8e8b89d5d40a55f8dbffd07
 F ext/fts5/fts5_hash.c 54dd25348a46ea62ea96322c572e08cd1fb37304
-F ext/fts5/fts5_index.c 6e0ac5835ab33a2cf97efd591acd4fc130490e0f
+F ext/fts5/fts5_index.c 2c4500c35072b049d1391bbb4e64e4c0e3d3dd43
 F ext/fts5/fts5_storage.c cb8b585bfb7870a36101f1a8fa0b0777f4d1b68d
 F ext/fts5/fts5_tcl.c f18eeb125d733f4e815a11679b971fa61cd7ec77
 F ext/fts5/fts5_tokenize.c 830eae0d35a5a5a90af34df65da3427f46d942fc
 F ext/fts5/fts5_unicode2.c f74f53316377068812a1fa5a37819e6b8124631d
-F ext/fts5/fts5_vocab.c e532f38a62d27fa662138a6cf33890b314225506
+F ext/fts5/fts5_vocab.c b54301e376f59f08f662b5dde1cfaf26e86e4db6
 F ext/fts5/fts5parse.y 777da8e5819f75c217982c79c29d014c293acac9
 F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
 F ext/fts5/test/fts5_common.tcl d9ea79fdbc9ecbb3541bf89d13ee0e03a8dc3d32
-F ext/fts5/test/fts5aa.test 5f221b82487abfb915e1b040eb4e305cf79a2ef5
+F ext/fts5/test/fts5aa.test 29409f14dec2ee67bd82ebf15111d6167b1003df
 F ext/fts5/test/fts5ab.test 6fe3a56731d15978afbb74ae51b355fc9310f2ad
 F ext/fts5/test/fts5ac.test 05008e00bd2761cc45df838a0988ecf318cbe1fd
 F ext/fts5/test/fts5ad.test 2141b0360dc4397bfed30f0b0d700fa64b44835d
@@ -136,24 +136,25 @@ F ext/fts5/test/fts5al.test fc60ebeac9d8e366e71309d4c31fa72199d711d7
 F ext/fts5/test/fts5aux.test d9cd26ee45ad5f628b4899f1ac5b757ce7a77bdf
 F ext/fts5/test/fts5auxdata.test c69b86092bf1a157172de5f9169731af3403179b
 F ext/fts5/test/fts5bigpl.test b1cfd00561350ab04994ba7dd9d48468e5e0ec3b
+F ext/fts5/test/fts5config.test c9cc535f3b36cde1e5a32bf579f3f5962a9e82b2
 F ext/fts5/test/fts5content.test 532e15b541254410adc7bfb51f94631cfe82de8f
 F ext/fts5/test/fts5corrupt.test 35bfdbbb3cdcea46ae7385f6432e9b5c574e70a1
 F ext/fts5/test/fts5corrupt2.test 7000030df189f1f3ca58b555b459bcbf9b8f8f77
 F ext/fts5/test/fts5corrupt3.test fe42c0ce0b58b7ad487a469049f91419d22c7459
 F ext/fts5/test/fts5dlidx.test 070531bd45685e545e3e6021deb543f730a4011b
 F ext/fts5/test/fts5doclist.test 635b80ac785627841a59c583bac702b55d49fdc5
-F ext/fts5/test/fts5ea.test ed163ed820fd503354bd7dcf9d3b0e3801ade962
+F ext/fts5/test/fts5ea.test c2f33a33d307b2d38e29f66323a67b7af0b082ea
 F ext/fts5/test/fts5eb.test 728a1f23f263548f5c29b29dfb851b5f2dbe723e
 F ext/fts5/test/fts5fault1.test b42d3296be8a75f557cf2cbce0d8b483fc9db45b
-F ext/fts5/test/fts5fault2.test 26c3d70648f691e2cc9391e14bbc11a973656383
+F ext/fts5/test/fts5fault2.test 28c36c843bb39ae855ba79827417ecc37f114341
 F ext/fts5/test/fts5fault3.test d6e9577d4312e331a913c72931bf131704efc8f3
-F ext/fts5/test/fts5fault4.test 6e5b1609a0e7d51e7598fa675db581b3b1bfbf7e
+F ext/fts5/test/fts5fault4.test 7301602e916261f0b277ed93f447fd871d5d7064
 F ext/fts5/test/fts5fault5.test 98e7e77bc1d8bb47c955e7d6dc870ab5736536e3
 F ext/fts5/test/fts5full.test 0924bdca5416a242103239ace79c6f5aa34bab8d
 F ext/fts5/test/fts5hash.test bdba7b591d503005d5a81871ba00a359daa1e969
 F ext/fts5/test/fts5integrity.test 98801bd0fb7c53a40bc770280134865d61724f3a
-F ext/fts5/test/fts5merge.test b985b6891e093a4b4c3c9683fe3cba7498fed690
-F ext/fts5/test/fts5near.test 3f9f64e16cac82725d03d4e04c661090f0b3b947
+F ext/fts5/test/fts5merge.test 8077454f2975a63f35761f4b8a718b3a808b7c9c
+F ext/fts5/test/fts5near.test d2e3343e62d438f2efd96ebcd83a0d30a16ea6dc
 F ext/fts5/test/fts5optimize.test 0028c90a7817d3e576d1148fc8dff17d89054e54
 F ext/fts5/test/fts5plan.test 89783f70dab89ff936ed6f21d88959b49c853a47
 F ext/fts5/test/fts5porter.test 50322599823cb8080a99f0ec0c39f7d0c12bcb5e
@@ -167,7 +168,7 @@ F ext/fts5/test/fts5unicode.test 79b3e34eb29ce4929628aa514a40cb467fdabe4d
 F ext/fts5/test/fts5unicode2.test 64a5267fd6082fcb46439892ebd0cbaa5c38acee
 F ext/fts5/test/fts5unindexed.test f388605341a476b6ab622b4c267cd168f59a5944
 F ext/fts5/test/fts5version.test dc34a735af6625a1a7a4a916a38d122071343887
-F ext/fts5/test/fts5vocab.test 2d1bddfb6e1effd9e1d2f5d1d25bf05e9ab33e64
+F ext/fts5/test/fts5vocab.test 80fb22850dd3b2c92a3896e6021605e08c0872aa
 F ext/fts5/tool/loadfts5.tcl add4d349ae5463c5f60b26e821c24e60ed8054d3
 F ext/fts5/tool/showfts5.tcl 921f33b30c3189deefd2b2cc81f951638544aaf1
 F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
@@ -1326,7 +1327,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 7aea8c6d99737c6c72078e0b4b9c5f8186021aa0
-R 5014cf90f97a250385093a02a58cfb68
+P 927d9a64e13c6b768f0a15475713192fcfaaf9e7
+R 820e0577a96c7901c9b911f2b08f8e07
 U dan
-Z e8178e8c15c67776f9bff619db326cbd
+Z b644c576eadef53c3df6a681b5fdaf76
index 5f3b901b63ea7e0b7ece59be2dc5dbc455398839..c5cb98658335376e0e77be53c22b94caadf3b32f 100644 (file)
@@ -1 +1 @@
-927d9a64e13c6b768f0a15475713192fcfaaf9e7
\ No newline at end of file
+47dbfadb994814c9349d4c9c113b862c2e97c01a
\ No newline at end of file