/ Check-in [8ff2b8f5]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add the "notindexed" option to fts4.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | fts4-notindexed
Files: files | file ages | folders
SHA1: 8ff2b8f5948ccddce70102e6d68d464c66e4f7ca
User & Date: dan 2013-06-21 17:30:47
Context
2013-06-21
18:18
Add a few more tests for the fts4 notindexed option. Closed-Leaf check-in: b53c0c41 user: dan tags: fts4-notindexed
17:30
Add the "notindexed" option to fts4. check-in: 8ff2b8f5 user: dan tags: fts4-notindexed
2013-06-20
14:07
Disable posix_fallocate() for all systems, all the time, unless the HAVE_POSIX_FALLOCATE compile-time macro is supplied. check-in: b6744622 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/fts3/fts3.c.

  1077   1077     int bNoDocsize = 0;             /* True to omit %_docsize table */
  1078   1078     int bDescIdx = 0;               /* True to store descending indexes */
  1079   1079     char *zPrefix = 0;              /* Prefix parameter value (or NULL) */
  1080   1080     char *zCompress = 0;            /* compress=? parameter (or NULL) */
  1081   1081     char *zUncompress = 0;          /* uncompress=? parameter (or NULL) */
  1082   1082     char *zContent = 0;             /* content=? parameter (or NULL) */
  1083   1083     char *zLanguageid = 0;          /* languageid=? parameter (or NULL) */
         1084  +  char **azNotindexed = 0;        /* The set of notindexed= columns */
         1085  +  int nNotindexed = 0;            /* Size of azNotindexed[] array */
  1084   1086   
  1085   1087     assert( strlen(argv[0])==4 );
  1086   1088     assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4)
  1087   1089          || (sqlite3_strnicmp(argv[0], "fts3", 4)==0 && !isFts4)
  1088   1090     );
  1089   1091   
  1090   1092     nDb = (int)strlen(argv[1]) + 1;
  1091   1093     nName = (int)strlen(argv[2]) + 1;
  1092   1094   
  1093         -  aCol = (const char **)sqlite3_malloc(sizeof(const char *) * (argc-2) );
  1094         -  if( !aCol ) return SQLITE_NOMEM;
  1095         -  memset((void *)aCol, 0, sizeof(const char *) * (argc-2));
         1095  +  nByte = sizeof(const char *) * (argc-2);
         1096  +  aCol = (const char **)sqlite3_malloc(nByte);
         1097  +  if( aCol ){
         1098  +    memset(aCol, 0, nByte);
         1099  +    azNotindexed = (char **)sqlite3_malloc(nByte);
         1100  +  }
         1101  +  if( azNotindexed ){
         1102  +    memset(azNotindexed, 0, nByte);
         1103  +  }
         1104  +  if( !aCol || !azNotindexed ){
         1105  +    rc = SQLITE_NOMEM;
         1106  +    goto fts3_init_out;
         1107  +  }
  1096   1108   
  1097   1109     /* Loop through all of the arguments passed by the user to the FTS3/4
  1098   1110     ** module (i.e. all the column names and special arguments). This loop
  1099   1111     ** does the following:
  1100   1112     **
  1101   1113     **   + Figures out the number of columns the FTSX table will have, and
  1102   1114     **     the number of bytes of space that must be allocated to store copies
................................................................................
  1127   1139         } aFts4Opt[] = {
  1128   1140           { "matchinfo",   9 },     /* 0 -> MATCHINFO */
  1129   1141           { "prefix",      6 },     /* 1 -> PREFIX */
  1130   1142           { "compress",    8 },     /* 2 -> COMPRESS */
  1131   1143           { "uncompress", 10 },     /* 3 -> UNCOMPRESS */
  1132   1144           { "order",       5 },     /* 4 -> ORDER */
  1133   1145           { "content",     7 },     /* 5 -> CONTENT */
  1134         -        { "languageid", 10 }      /* 6 -> LANGUAGEID */
         1146  +        { "languageid", 10 },     /* 6 -> LANGUAGEID */
         1147  +        { "notindexed", 10 }      /* 7 -> NOTINDEXED */
  1135   1148         };
  1136   1149   
  1137   1150         int iOpt;
  1138   1151         if( !zVal ){
  1139   1152           rc = SQLITE_NOMEM;
  1140   1153         }else{
  1141   1154           for(iOpt=0; iOpt<SizeofArray(aFts4Opt); iOpt++){
................................................................................
  1193   1206   
  1194   1207               case 6:              /* LANGUAGEID */
  1195   1208                 assert( iOpt==6 );
  1196   1209                 sqlite3_free(zLanguageid);
  1197   1210                 zLanguageid = zVal;
  1198   1211                 zVal = 0;
  1199   1212                 break;
         1213  +
         1214  +            case 7:              /* NOTINDEXED */
         1215  +              azNotindexed[nNotindexed++] = zVal;
         1216  +              zVal = 0;
         1217  +              break;
  1200   1218             }
  1201   1219           }
  1202   1220           sqlite3_free(zVal);
  1203   1221         }
  1204   1222       }
  1205   1223   
  1206   1224       /* Otherwise, the argument is a column name. */
................................................................................
  1264   1282     }
  1265   1283     if( rc!=SQLITE_OK ) goto fts3_init_out;
  1266   1284   
  1267   1285     /* Allocate and populate the Fts3Table structure. */
  1268   1286     nByte = sizeof(Fts3Table) +                  /* Fts3Table */
  1269   1287             nCol * sizeof(char *) +              /* azColumn */
  1270   1288             nIndex * sizeof(struct Fts3Index) +  /* aIndex */
         1289  +          nCol * sizeof(u8) +                  /* abNotindexed */
  1271   1290             nName +                              /* zName */
  1272   1291             nDb +                                /* zDb */
  1273   1292             nString;                             /* Space for azColumn strings */
  1274   1293     p = (Fts3Table*)sqlite3_malloc(nByte);
  1275   1294     if( p==0 ){
  1276   1295       rc = SQLITE_NOMEM;
  1277   1296       goto fts3_init_out;
................................................................................
  1297   1316   
  1298   1317     p->aIndex = (struct Fts3Index *)&p->azColumn[nCol];
  1299   1318     memcpy(p->aIndex, aIndex, sizeof(struct Fts3Index) * nIndex);
  1300   1319     p->nIndex = nIndex;
  1301   1320     for(i=0; i<nIndex; i++){
  1302   1321       fts3HashInit(&p->aIndex[i].hPending, FTS3_HASH_STRING, 1);
  1303   1322     }
         1323  +  p->abNotindexed = (u8 *)&p->aIndex[nIndex];
  1304   1324   
  1305   1325     /* Fill in the zName and zDb fields of the vtab structure. */
  1306         -  zCsr = (char *)&p->aIndex[nIndex];
         1326  +  zCsr = (char *)&p->abNotindexed[nCol];
  1307   1327     p->zName = zCsr;
  1308   1328     memcpy(zCsr, argv[2], nName);
  1309   1329     zCsr += nName;
  1310   1330     p->zDb = zCsr;
  1311   1331     memcpy(zCsr, argv[1], nDb);
  1312   1332     zCsr += nDb;
  1313   1333   
................................................................................
  1320   1340       zCsr[n] = '\0';
  1321   1341       sqlite3Fts3Dequote(zCsr);
  1322   1342       p->azColumn[iCol] = zCsr;
  1323   1343       zCsr += n+1;
  1324   1344       assert( zCsr <= &((char *)p)[nByte] );
  1325   1345     }
  1326   1346   
  1327         -  if( (zCompress==0)!=(zUncompress==0) ){
         1347  +  /* Fill in the abNotindexed array */
         1348  +  for(iCol=0; iCol<nCol; iCol++){
         1349  +    int n = strlen(p->azColumn[iCol]);
         1350  +    for(i=0; i<nNotindexed; i++){
         1351  +      char *zNot = azNotindexed[i];
         1352  +      if( zNot && 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n) ){
         1353  +        p->abNotindexed[iCol] = 1;
         1354  +        sqlite3_free(zNot);
         1355  +        azNotindexed[i] = 0;
         1356  +      }
         1357  +    }
         1358  +  }
         1359  +  for(i=0; i<nNotindexed; i++){
         1360  +    if( azNotindexed[i] ){
         1361  +      *pzErr = sqlite3_mprintf("no such column: %s", azNotindexed[i]);
         1362  +      rc = SQLITE_ERROR;
         1363  +    }
         1364  +  }
         1365  +
         1366  +  if( rc==SQLITE_OK && (zCompress==0)!=(zUncompress==0) ){
  1328   1367       char const *zMiss = (zCompress==0 ? "compress" : "uncompress");
  1329   1368       rc = SQLITE_ERROR;
  1330   1369       *pzErr = sqlite3_mprintf("missing %s parameter in fts4 constructor", zMiss);
  1331   1370     }
  1332   1371     p->zReadExprlist = fts3ReadExprList(p, zUncompress, &rc);
  1333   1372     p->zWriteExprlist = fts3WriteExprList(p, zCompress, &rc);
  1334   1373     if( rc!=SQLITE_OK ) goto fts3_init_out;
................................................................................
  1361   1400   fts3_init_out:
  1362   1401     sqlite3_free(zPrefix);
  1363   1402     sqlite3_free(aIndex);
  1364   1403     sqlite3_free(zCompress);
  1365   1404     sqlite3_free(zUncompress);
  1366   1405     sqlite3_free(zContent);
  1367   1406     sqlite3_free(zLanguageid);
         1407  +  for(i=0; i<nNotindexed; i++) sqlite3_free(azNotindexed[i]);
  1368   1408     sqlite3_free((void *)aCol);
         1409  +  sqlite3_free((void *)azNotindexed);
  1369   1410     if( rc!=SQLITE_OK ){
  1370   1411       if( p ){
  1371   1412         fts3DisconnectMethod((sqlite3_vtab *)p);
  1372   1413       }else if( pTokenizer ){
  1373   1414         pTokenizer->pModule->xDestroy(pTokenizer);
  1374   1415       }
  1375   1416     }else{

Changes to ext/fts3/fts3Int.h.

   202    202   struct Fts3Table {
   203    203     sqlite3_vtab base;              /* Base class used by SQLite core */
   204    204     sqlite3 *db;                    /* The database connection */
   205    205     const char *zDb;                /* logical database name */
   206    206     const char *zName;              /* virtual table name */
   207    207     int nColumn;                    /* number of named columns in virtual table */
   208    208     char **azColumn;                /* column names.  malloced */
          209  +  u8 *abNotindexed;               /* True for 'notindexed' columns */
   209    210     sqlite3_tokenizer *pTokenizer;  /* tokenizer for inserts and queries */
   210    211     char *zContentTbl;              /* content=xxx option, or NULL */
   211    212     char *zLanguageid;              /* languageid=xxx option, or NULL */
   212    213     u8 bAutoincrmerge;              /* True if automerge=1 */
   213    214     u32 nLeafAdd;                   /* Number of leaf blocks added this trans */
   214    215   
   215    216     /* Precompiled statements used by the implementation. Each of these 

Changes to ext/fts3/fts3_write.c.

   896    896     Fts3Table *p, 
   897    897     int iLangid, 
   898    898     sqlite3_value **apVal, 
   899    899     u32 *aSz
   900    900   ){
   901    901     int i;                          /* Iterator variable */
   902    902     for(i=2; i<p->nColumn+2; i++){
   903         -    const char *zText = (const char *)sqlite3_value_text(apVal[i]);
   904         -    int rc = fts3PendingTermsAdd(p, iLangid, zText, i-2, &aSz[i-2]);
   905         -    if( rc!=SQLITE_OK ){
   906         -      return rc;
          903  +    int iCol = i-2;
          904  +    if( p->abNotindexed[iCol]==0 ){
          905  +      const char *zText = (const char *)sqlite3_value_text(apVal[i]);
          906  +      int rc = fts3PendingTermsAdd(p, iLangid, zText, iCol, &aSz[iCol]);
          907  +      if( rc!=SQLITE_OK ){
          908  +        return rc;
          909  +      }
          910  +      aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]);
   907    911       }
   908         -    aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]);
   909    912     }
   910    913     return SQLITE_OK;
   911    914   }
   912    915   
   913    916   /*
   914    917   ** This function is called by the xUpdate() method for an INSERT operation.
   915    918   ** The apVal parameter is passed a copy of the apVal argument passed by
................................................................................
  1048   1051     rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid);
  1049   1052     if( rc==SQLITE_OK ){
  1050   1053       if( SQLITE_ROW==sqlite3_step(pSelect) ){
  1051   1054         int i;
  1052   1055         int iLangid = langidFromSelect(p, pSelect);
  1053   1056         rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0));
  1054   1057         for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){
  1055         -        const char *zText = (const char *)sqlite3_column_text(pSelect, i);
  1056         -        rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[i-1]);
  1057         -        aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i);
         1058  +        int iCol = i-1;
         1059  +        if( p->abNotindexed[iCol]==0 ){
         1060  +          const char *zText = (const char *)sqlite3_column_text(pSelect, i);
         1061  +          rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[iCol]);
         1062  +          aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i);
         1063  +        }
  1058   1064         }
  1059   1065         if( rc!=SQLITE_OK ){
  1060   1066           sqlite3_reset(pSelect);
  1061   1067           *pRC = rc;
  1062   1068           return;
  1063   1069         }
  1064   1070         *pbFound = 1;
................................................................................
  3292   3298   
  3293   3299       while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
  3294   3300         int iCol;
  3295   3301         int iLangid = langidFromSelect(p, pStmt);
  3296   3302         rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0));
  3297   3303         memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1));
  3298   3304         for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
  3299         -        const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
  3300         -        rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]);
  3301         -        aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1);
         3305  +        if( p->abNotindexed[iCol]==0 ){
         3306  +          const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
         3307  +          rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]);
         3308  +          aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1);
         3309  +        }
  3302   3310         }
  3303   3311         if( p->bHasDocsize ){
  3304   3312           fts3InsertDocsize(&rc, p, aSz);
  3305   3313         }
  3306   3314         if( rc!=SQLITE_OK ){
  3307   3315           sqlite3_finalize(pStmt);
  3308   3316           pStmt = 0;
................................................................................
  5097   5105       sqlite3_tokenizer *pT = p->pTokenizer;
  5098   5106       sqlite3_tokenizer_module const *pModule = pT->pModule;
  5099   5107      
  5100   5108       assert( pCsr->isRequireSeek==0 );
  5101   5109       iDocid = sqlite3_column_int64(pCsr->pStmt, 0);
  5102   5110     
  5103   5111       for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){
  5104         -      const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1);
  5105         -      sqlite3_tokenizer_cursor *pTC = 0;
  5106         -  
  5107         -      rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC);
  5108         -      while( rc==SQLITE_OK ){
  5109         -        char const *zToken;       /* Buffer containing token */
  5110         -        int nToken = 0;           /* Number of bytes in token */
  5111         -        int iDum1 = 0, iDum2 = 0; /* Dummy variables */
  5112         -        int iPos = 0;             /* Position of token in zText */
  5113         -  
  5114         -        rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
  5115         -        for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
  5116         -          Fts3PhraseToken *pPT = pDef->pToken;
  5117         -          if( (pDef->iCol>=p->nColumn || pDef->iCol==i)
  5118         -           && (pPT->bFirst==0 || iPos==0)
  5119         -           && (pPT->n==nToken || (pPT->isPrefix && pPT->n<nToken))
  5120         -           && (0==memcmp(zToken, pPT->z, pPT->n))
  5121         -          ){
  5122         -            fts3PendingListAppend(&pDef->pList, iDocid, i, iPos, &rc);
         5112  +      if( p->abNotindexed[i]==0 ){
         5113  +        const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1);
         5114  +        sqlite3_tokenizer_cursor *pTC = 0;
         5115  +
         5116  +        rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC);
         5117  +        while( rc==SQLITE_OK ){
         5118  +          char const *zToken;       /* Buffer containing token */
         5119  +          int nToken = 0;           /* Number of bytes in token */
         5120  +          int iDum1 = 0, iDum2 = 0; /* Dummy variables */
         5121  +          int iPos = 0;             /* Position of token in zText */
         5122  +
         5123  +          rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
         5124  +          for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
         5125  +            Fts3PhraseToken *pPT = pDef->pToken;
         5126  +            if( (pDef->iCol>=p->nColumn || pDef->iCol==i)
         5127  +                && (pPT->bFirst==0 || iPos==0)
         5128  +                && (pPT->n==nToken || (pPT->isPrefix && pPT->n<nToken))
         5129  +                && (0==memcmp(zToken, pPT->z, pPT->n))
         5130  +              ){
         5131  +              fts3PendingListAppend(&pDef->pList, iDocid, i, iPos, &rc);
         5132  +            }
  5123   5133             }
  5124   5134           }
         5135  +        if( pTC ) pModule->xClose(pTC);
         5136  +        if( rc==SQLITE_DONE ) rc = SQLITE_OK;
  5125   5137         }
  5126         -      if( pTC ) pModule->xClose(pTC);
  5127         -      if( rc==SQLITE_DONE ) rc = SQLITE_OK;
  5128         -    }
  5129         -  
  5130         -    for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
  5131         -      if( pDef->pList ){
  5132         -        rc = fts3PendingListAppendVarint(&pDef->pList, 0);
         5138  +
         5139  +      for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
         5140  +        if( pDef->pList ){
         5141  +          rc = fts3PendingListAppendVarint(&pDef->pList, 0);
         5142  +        }
  5133   5143         }
  5134   5144       }
  5135   5145     }
  5136   5146   
  5137   5147     return rc;
  5138   5148   }
  5139   5149   

Added test/fts4noti.test.

            1  +# 2013 June 21
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#*************************************************************************
           11  +# This file implements regression tests for SQLite library.  The
           12  +# focus of this script is testing the notindexed=xxx FTS4 option.
           13  +#
           14  +
           15  +set testdir [file dirname $argv0]
           16  +source $testdir/tester.tcl
           17  +set ::testprefix fts4noti
           18  +
           19  +# If SQLITE_ENABLE_FTS3 is defined, omit this file.
           20  +ifcapable !fts3 {
           21  +  finish_test
           22  +  return
           23  +}
           24  +
           25  +
           26  +#-------------------------------------------------------------------------
           27  +# Test that typos in "notindexed=" column names are detected.
           28  +#
           29  +do_execsql_test 1.0 {
           30  +  CREATE TABLE cc(a, b, c);
           31  +}
           32  +foreach {tn arg res} {
           33  +  1 "(b, c, notindexed=a)"                  {1 {no such column: a}}
           34  +  2 "(a, b, notindexed=a)"                                   {0 {}}
           35  +  3 "(a, b, notindexed=a, notindexed=a)"                     {0 {}}
           36  +  4 "(notindexed=a, a, b)"                                   {0 {}}
           37  +  5 "(notindexed=a, notindexed=b, notindexed=c, a, b, c, d)" {0 {}}
           38  +  6 "(notindexed=a, notindexed=B, notindexed=c, a, b, c, d)" {0 {}}
           39  +  7 "(notindexed=a, notindexed=b, notindexed=c, a, B, c, d)" {0 {}}
           40  +  8 "(notindexed=d, content=cc)" {1 {no such column: d}}
           41  +  9 "(notindexed=a, content=cc)" {0 {}}
           42  +} {
           43  +  do_catchsql_test 1.$tn "CREATE VIRTUAL TABLE t1 USING fts4 $arg" $res
           44  +  if {[lindex $res 0]==0} { execsql "DROP TABLE t1" }
           45  +}
           46  +
           47  +do_execsql_test 1.x { SELECT name FROM sqlite_master } {cc}
           48  +
           49  +
           50  +#-------------------------------------------------------------------------
           51  +# Test that notindexed columns are not indexed.
           52  +#
           53  +do_execsql_test 2.1 {
           54  +  CREATE VIRTUAL TABLE t1 USING fts4(a, b, c, notindexed=b);
           55  +  INSERT INTO t1 VALUES('one two', 'three four', 'five six');
           56  +  INSERT INTO t1 VALUES('three four', 'five six', 'one two');
           57  +}
           58  +do_execsql_test 2.2 { SELECT docid FROM t1 WHERE t1 MATCH 'one' } {1 2}
           59  +do_execsql_test 2.3 { SELECT docid FROM t1 WHERE t1 MATCH 'three' } {2}
           60  +do_execsql_test 2.4 { SELECT docid FROM t1 WHERE t1 MATCH 'five' } {1}
           61  +
           62  +do_execsql_test 2.5 { INSERT INTO t1(t1) VALUES('optimize') }
           63  +
           64  +do_execsql_test 2.6 { SELECT docid FROM t1 WHERE t1 MATCH 'one' } {1 2}
           65  +do_execsql_test 2.7 { SELECT docid FROM t1 WHERE t1 MATCH 'three' } {2}
           66  +do_execsql_test 2.8 { SELECT docid FROM t1 WHERE t1 MATCH 'five' } {1}
           67  +
           68  +do_execsql_test 2.9 { INSERT INTO t1(t1) VALUES('rebuild') }
           69  +
           70  +do_execsql_test 2.10 { SELECT docid FROM t1 WHERE t1 MATCH 'one' } {1 2}
           71  +do_execsql_test 2.11 { SELECT docid FROM t1 WHERE t1 MATCH 'three' } {2}
           72  +do_execsql_test 2.12 { SELECT docid FROM t1 WHERE t1 MATCH 'five' } {1}
           73  +
           74  +do_execsql_test 2.13 { 
           75  +  SELECT * FROM t1 WHERE docid=1
           76  +} {{one two} {three four} {five six}}
           77  +do_execsql_test 2.14 { 
           78  +  SELECT * FROM t1 WHERE docid=2
           79  +} {{three four} {five six} {one two}}
           80  +
           81  +do_execsql_test 2.x { DROP TABLE t1 }
           82  +
           83  +#-------------------------------------------------------------------------
           84  +# Test that notindexed columns are not scanned for deferred tokens.
           85  +#
           86  +
           87  +do_execsql_test 3.1 {
           88  +  CREATE VIRTUAL TABLE t2 USING fts4(x, y, notindexed=x);
           89  +}
           90  +do_test 3.2 {
           91  +  set v [string repeat " 1" 50000]
           92  +  set v1 "x $v"
           93  +  set v2 "y $v"
           94  +  execsql { 
           95  +    INSERT INTO t2 VALUES(1, 'x y z');
           96  +    INSERT INTO t2 VALUES(2, $v1);
           97  +    INSERT INTO t2 VALUES(3, $v2);
           98  +    INSERT INTO t2 VALUES(4, $v2);
           99  +    INSERT INTO t2 VALUES(5, $v2);
          100  +    INSERT INTO t2 VALUES(6, $v2);
          101  +  }
          102  +} {}
          103  +
          104  +do_execsql_test 3.3 { SELECT x FROM t2 WHERE t2 MATCH '2' } {}
          105  +do_execsql_test 3.4 { SELECT x FROM t2 WHERE t2 MATCH '1' } {2 3 4 5 6}
          106  +do_execsql_test 3.5 { SELECT x FROM t2 WHERE t2 MATCH 'x' } {1 2}
          107  +do_execsql_test 3.6 { SELECT x FROM t2 WHERE t2 MATCH 'x 1' } {2}
          108  +  
          109  +
          110  +
          111  +finish_test

Changes to test/permutations.test.

   190    190     fts3near.test fts3query.test fts3shared.test fts3snippet.test 
   191    191     fts3sort.test
   192    192     fts3fault.test fts3malloc.test fts3matchinfo.test
   193    193     fts3aux1.test fts3comp1.test fts3auto.test
   194    194     fts4aa.test fts4content.test
   195    195     fts3conf.test fts3prefix.test fts3fault2.test fts3corrupt.test
   196    196     fts3corrupt2.test fts3first.test fts4langid.test fts4merge.test
   197         -  fts4check.test fts4unicode.test
          197  +  fts4check.test fts4unicode.test fts4noti.test
   198    198   }
   199    199   
   200    200   test_suite "nofaultsim" -prefix "" -description {
   201    201     "Very" quick test suite. Runs in less than 5 minutes on a workstation. 
   202    202     This test suite is the same as the "quick" tests, except that some files
   203    203     that test malloc and IO errors are omitted.
   204    204   } -files [