/ Check-in [2a7170f0]
Login

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

Overview
Comment:Cherrypick the FTS fix in [c05c3fd20d9] into the nx-devkit branch. Ticket [edb497982c].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | nx-devkit
Files: files | file ages | folders
SHA1: 2a7170f03c746473aca38ddc4b4a4091fe8331eb
User & Date: drh 2012-01-25 22:08:39
Original Comment: Cherrypick the FTS fix in [c05c3fd0d] into the nx-devkit branch. Ticket [edb497982c].
Context
2012-01-30
16:13
Do not rely on the _WIN32_WINNT macro as vs2005 does not define it by default. Instead, always assume winNT unless the makefile explicitly sets SQLITE_OS_WINNT=0. check-in: 4f0997c7 user: drh tags: nx-devkit
2012-01-25
22:08
Cherrypick the FTS fix in [c05c3fd20d9] into the nx-devkit branch. Ticket [edb497982c]. check-in: 2a7170f0 user: drh tags: nx-devkit
2012-01-20
15:05
Cherrypick the fix from [629108c8e5376f989] into the nx-devkit branch. check-in: d7374568 user: drh tags: nx-devkit
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/fts3/fts3.c.

  2596   2596           sqlite3_int64 *pi = (isPrefix ? &iLeavesEndBlock : 0);
  2597   2597           rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &iStartBlock, pi);
  2598   2598           if( rc!=SQLITE_OK ) goto finished;
  2599   2599           if( isPrefix==0 && isScan==0 ) iLeavesEndBlock = iStartBlock;
  2600   2600         }
  2601   2601    
  2602   2602         rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1, 
  2603         -          iStartBlock, iLeavesEndBlock, iEndBlock, zRoot, nRoot, &pSeg
         2603  +          (isPrefix==0 && isScan==0),
         2604  +          iStartBlock, iLeavesEndBlock, 
         2605  +          iEndBlock, zRoot, nRoot, &pSeg
  2604   2606         );
  2605   2607         if( rc!=SQLITE_OK ) goto finished;
  2606   2608         rc = fts3SegReaderCursorAppend(pCsr, pSeg);
  2607   2609       }
  2608   2610     }
  2609   2611   
  2610   2612    finished:

Changes to ext/fts3/fts3Int.h.

   397    397   
   398    398   
   399    399   /* fts3_write.c */
   400    400   int sqlite3Fts3UpdateMethod(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*);
   401    401   int sqlite3Fts3PendingTermsFlush(Fts3Table *);
   402    402   void sqlite3Fts3PendingTermsClear(Fts3Table *);
   403    403   int sqlite3Fts3Optimize(Fts3Table *);
   404         -int sqlite3Fts3SegReaderNew(int, sqlite3_int64,
          404  +int sqlite3Fts3SegReaderNew(int, int, sqlite3_int64,
   405    405     sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**);
   406    406   int sqlite3Fts3SegReaderPending(
   407    407     Fts3Table*,int,const char*,int,int,Fts3SegReader**);
   408    408   void sqlite3Fts3SegReaderFree(Fts3SegReader *);
   409    409   int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, sqlite3_stmt **);
   410    410   int sqlite3Fts3ReadLock(Fts3Table *);
   411    411   int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*);

Changes to ext/fts3/fts3_write.c.

   106    106   **
   107    107   **   fts3SegReaderNext()
   108    108   **   fts3SegReaderFirstDocid()
   109    109   **   fts3SegReaderNextDocid()
   110    110   */
   111    111   struct Fts3SegReader {
   112    112     int iIdx;                       /* Index within level, or 0x7FFFFFFF for PT */
          113  +  int bLookup;                    /* True for a lookup only */
   113    114   
   114    115     sqlite3_int64 iStartBlock;      /* Rowid of first leaf block to traverse */
   115    116     sqlite3_int64 iLeafEndBlock;    /* Rowid of final leaf block to traverse */
   116    117     sqlite3_int64 iEndBlock;        /* Rowid of final block in segment (or 0) */
   117    118     sqlite3_int64 iCurrentBlock;    /* Current leaf block (or 0) */
   118    119   
   119    120     char *aNode;                    /* Pointer to node data (or NULL) */
................................................................................
  1083   1084     while( pReader->pBlob && rc==SQLITE_OK 
  1084   1085        &&  (pFrom - pReader->aNode + nByte)>pReader->nPopulate
  1085   1086     ){
  1086   1087       rc = fts3SegReaderIncrRead(pReader);
  1087   1088     }
  1088   1089     return rc;
  1089   1090   }
         1091  +
         1092  +/*
         1093  +** Set an Fts3SegReader cursor to point at EOF.
         1094  +*/
         1095  +static void fts3SegReaderSetEof(Fts3SegReader *pSeg){
         1096  +  if( !fts3SegReaderIsRootOnly(pSeg) ){
         1097  +    sqlite3_free(pSeg->aNode);
         1098  +    sqlite3_blob_close(pSeg->pBlob);
         1099  +    pSeg->pBlob = 0;
         1100  +  }
         1101  +  pSeg->aNode = 0;
         1102  +}
  1090   1103   
  1091   1104   /*
  1092   1105   ** Move the iterator passed as the first argument to the next term in the
  1093   1106   ** segment. If successful, SQLITE_OK is returned. If there is no next term,
  1094   1107   ** SQLITE_DONE. Otherwise, an SQLite error code.
  1095   1108   */
  1096   1109   static int fts3SegReaderNext(
................................................................................
  1123   1136           pReader->aNode = pReader->aDoclist = pList->aData;
  1124   1137           pReader->ppNextElem++;
  1125   1138           assert( pReader->aNode );
  1126   1139         }
  1127   1140         return SQLITE_OK;
  1128   1141       }
  1129   1142   
  1130         -    if( !fts3SegReaderIsRootOnly(pReader) ){
  1131         -      sqlite3_free(pReader->aNode);
  1132         -      sqlite3_blob_close(pReader->pBlob);
  1133         -      pReader->pBlob = 0;
  1134         -    }
  1135         -    pReader->aNode = 0;
         1143  +    fts3SegReaderSetEof(pReader);
  1136   1144   
  1137   1145       /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf 
  1138   1146       ** blocks have already been traversed.  */
  1139   1147       assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock );
  1140   1148       if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){
  1141   1149         return SQLITE_OK;
  1142   1150       }
................................................................................
  1375   1383   }
  1376   1384   
  1377   1385   /*
  1378   1386   ** Allocate a new SegReader object.
  1379   1387   */
  1380   1388   int sqlite3Fts3SegReaderNew(
  1381   1389     int iAge,                       /* Segment "age". */
         1390  +  int bLookup,                    /* True for a lookup only */
  1382   1391     sqlite3_int64 iStartLeaf,       /* First leaf to traverse */
  1383   1392     sqlite3_int64 iEndLeaf,         /* Final leaf to traverse */
  1384   1393     sqlite3_int64 iEndBlock,        /* Final block of segment */
  1385   1394     const char *zRoot,              /* Buffer containing root node */
  1386   1395     int nRoot,                      /* Size of buffer containing root node */
  1387   1396     Fts3SegReader **ppReader        /* OUT: Allocated Fts3SegReader */
  1388   1397   ){
................................................................................
  1397   1406   
  1398   1407     pReader = (Fts3SegReader *)sqlite3_malloc(sizeof(Fts3SegReader) + nExtra);
  1399   1408     if( !pReader ){
  1400   1409       return SQLITE_NOMEM;
  1401   1410     }
  1402   1411     memset(pReader, 0, sizeof(Fts3SegReader));
  1403   1412     pReader->iIdx = iAge;
         1413  +  pReader->bLookup = bLookup;
  1404   1414     pReader->iStartBlock = iStartLeaf;
  1405   1415     pReader->iLeafEndBlock = iEndLeaf;
  1406   1416     pReader->iEndBlock = iEndBlock;
  1407   1417   
  1408   1418     if( nExtra ){
  1409   1419       /* The entire segment is stored in the root node. */
  1410   1420       pReader->aNode = (char *)&pReader[1];
................................................................................
  2399   2409     /* If the Fts3SegFilter defines a specific term (or term prefix) to search 
  2400   2410     ** for, then advance each segment iterator until it points to a term of
  2401   2411     ** equal or greater value than the specified term. This prevents many
  2402   2412     ** unnecessary merge/sort operations for the case where single segment
  2403   2413     ** b-tree leaf nodes contain more than one term.
  2404   2414     */
  2405   2415     for(i=0; pCsr->bRestart==0 && i<pCsr->nSegment; i++){
         2416  +    int res;
  2406   2417       Fts3SegReader *pSeg = pCsr->apSegment[i];
  2407   2418       do {
  2408   2419         int rc = fts3SegReaderNext(p, pSeg, 0);
  2409   2420         if( rc!=SQLITE_OK ) return rc;
  2410         -    }while( zTerm && fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 );
         2421  +    }while( zTerm && (res = fts3SegReaderTermCmp(pSeg, zTerm, nTerm))<0 );
         2422  +
         2423  +    if( pSeg->bLookup && res!=0 ){
         2424  +      fts3SegReaderSetEof(pSeg);
         2425  +    }
  2411   2426     }
  2412   2427     fts3SegReaderSort(pCsr->apSegment, nSeg, nSeg, fts3SegReaderCmp);
  2413   2428   
  2414   2429     return SQLITE_OK;
  2415   2430   }
  2416   2431   
  2417   2432   int sqlite3Fts3SegReaderStart(
................................................................................
  2524   2539       int nMerge;
  2525   2540       int i;
  2526   2541     
  2527   2542       /* Advance the first pCsr->nAdvance entries in the apSegment[] array
  2528   2543       ** forward. Then sort the list in order of current term again.  
  2529   2544       */
  2530   2545       for(i=0; i<pCsr->nAdvance; i++){
  2531         -      rc = fts3SegReaderNext(p, apSegment[i], 0);
         2546  +      Fts3SegReader *pSeg = apSegment[i];
         2547  +      if( pSeg->bLookup ){
         2548  +        fts3SegReaderSetEof(pSeg);
         2549  +      }else{
         2550  +        rc = fts3SegReaderNext(p, pSeg, 0);
         2551  +      }
  2532   2552         if( rc!=SQLITE_OK ) return rc;
  2533   2553       }
  2534   2554       fts3SegReaderSort(apSegment, nSegment, pCsr->nAdvance, fts3SegReaderCmp);
  2535   2555       pCsr->nAdvance = 0;
  2536   2556   
  2537   2557       /* If all the seg-readers are at EOF, we're finished. return SQLITE_OK. */
  2538   2558       assert( rc==SQLITE_OK );

Changes to test/fts3auto.test.

   569    569   #--------------------------------------------------------------------------
   570    570   # The following test cases - fts3auto-5.* - focus on using prefix indexes.
   571    571   #
   572    572   set chunkconfig [fts3_configure_incr_load 1 1]
   573    573   foreach {tn create pending} {
   574    574     1    "fts4(a, b)"                                  1
   575    575     2    "fts4(a, b, order=ASC, prefix=1)"             1
   576         -  3    "fts4(a, b, order=ASC,  prefix=1,3)"          0
   577         -  4    "fts4(a, b, order=DESC, prefix=2,4)"          0
   578         -  5    "fts4(a, b, order=DESC, prefix=1)"            0
   579         -  6    "fts4(a, b, order=ASC,  prefix=1,3)"          0
          576  +  3    "fts4(a, b, order=ASC,  prefix=\"1,3\")"      0
          577  +  4    "fts4(a, b, order=DESC, prefix=\"2,4\")"      0
          578  +  5    "fts4(a, b, order=DESC, prefix=\"1\")"        0
          579  +  6    "fts4(a, b, order=ASC,  prefix=\"1,3\")"      0
   580    580   } {
   581    581   
   582    582     execsql [subst {
   583    583       DROP TABLE IF EXISTS t1;
   584    584       CREATE VIRTUAL TABLE t1 USING $create;
   585    585     }]
   586    586   

Added test/fts3prefix2.test.

            1  +# 2012 January 25
            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 FTS3 module.
           13  +#
           14  +
           15  +set testdir [file dirname $argv0]
           16  +source $testdir/tester.tcl
           17  +set testprefix fts3prefix2
           18  +
           19  +ifcapable !fts3 {
           20  +  finish_test
           21  +  return
           22  +}
           23  +
           24  +do_execsql_test 1.0 { PRAGMA page_size = 512 }
           25  +do_execsql_test 1.1 { 
           26  +  CREATE VIRTUAL TABLE t1 USING fts4(x, prefix="2,3");
           27  +
           28  +  BEGIN;
           29  +    INSERT INTO t1 VALUES('T TX T TX T TX T TX T TX');
           30  +    INSERT INTO t1 SELECT * FROM t1;                       -- 2
           31  +    INSERT INTO t1 SELECT * FROM t1;                       -- 4
           32  +    INSERT INTO t1 SELECT * FROM t1;                       -- 8
           33  +    INSERT INTO t1 SELECT * FROM t1;                       -- 16
           34  +    INSERT INTO t1 SELECT * FROM t1;                       -- 32
           35  +    INSERT INTO t1 SELECT * FROM t1;                       -- 64
           36  +    INSERT INTO t1 SELECT * FROM t1;                       -- 128
           37  +    INSERT INTO t1 SELECT * FROM t1;                       -- 256
           38  +    INSERT INTO t1 SELECT * FROM t1;                       -- 512
           39  +    INSERT INTO t1 SELECT * FROM t1;                       -- 1024
           40  +    INSERT INTO t1 SELECT * FROM t1;                       -- 2048
           41  +  COMMIT;
           42  +}
           43  +
           44  +do_execsql_test 1.2 {
           45  +  INSERT INTO t1 SELECT * FROM t1 LIMIT 10;
           46  +  INSERT INTO t1 SELECT * FROM t1 LIMIT 10;
           47  +  INSERT INTO t1 SELECT * FROM t1 LIMIT 10;
           48  +  DELETE FROM t1 WHERE docid > 5;
           49  +}
           50  +
           51  +do_execsql_test 1.3 {
           52  +  SELECT * FROM t1 WHERE t1 MATCH 'T*';
           53  +} {
           54  +  {T TX T TX T TX T TX T TX}
           55  +  {T TX T TX T TX T TX T TX}
           56  +  {T TX T TX T TX T TX T TX}
           57  +  {T TX T TX T TX T TX T TX}
           58  +  {T TX T TX T TX T TX T TX}
           59  +}
           60  +
           61  +finish_test
           62  +