]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Handle equality and range constraints on the "term" column of fts5vocab tables. Also...
authordan <dan@noemail.net>
Sat, 17 Oct 2015 19:49:01 +0000 (19:49 +0000)
committerdan <dan@noemail.net>
Sat, 17 Oct 2015 19:49:01 +0000 (19:49 +0000)
FossilOrigin-Name: 6020d96ab47a0bebe41f691a3f44fd55d8b2d2b7

ext/fts5/fts5Int.h
ext/fts5/fts5_index.c
ext/fts5/fts5_main.c
ext/fts5/fts5_vocab.c
ext/fts5/test/fts5vocab.test
manifest
manifest.uuid

index 3671da1f125f7fb5bd4e47e6f241863b6536d9a5..bef185b07b6e117f75f9a1e514883a5b3a3e8199 100644 (file)
@@ -475,7 +475,7 @@ int sqlite3Fts5GetTokenizer(
   char **pzErr
 );
 
-Fts5Index *sqlite3Fts5IndexFromCsrid(Fts5Global*, i64, int*);
+Fts5Index *sqlite3Fts5IndexFromCsrid(Fts5Global*, i64, Fts5Config **);
 
 /*
 ** End of interface to code in fts5.c.
index 5f3316f623c32f62f57a0d4f09cff5eb68e8d4f2..e006c9b36d1c67643a445d6eecf802ef368584ae 100644 (file)
@@ -4597,9 +4597,7 @@ int sqlite3Fts5IndexQuery(
   Fts5Buffer buf = {0, 0, 0};
 
   /* If the QUERY_SCAN flag is set, all other flags must be clear. */
-  assert( (flags & FTS5INDEX_QUERY_SCAN)==0
-       || (flags & FTS5INDEX_QUERY_SCAN)==FTS5INDEX_QUERY_SCAN
-  );
+  assert( (flags & FTS5INDEX_QUERY_SCAN)==0 || flags==FTS5INDEX_QUERY_SCAN );
 
   if( sqlite3Fts5BufferGrow(&p->rc, &buf, nToken+1)==0 ){
     memcpy(&buf.p[1], pToken, nToken);
index a301a82f24c732964b363a7e148bbc01dd1912d6..a133cf41b9cf2458af12e8e6d1cb97b30005d61c 100644 (file)
@@ -2021,20 +2021,20 @@ static void fts5ApiCallback(
 ** Given cursor id iId, return a pointer to the corresponding Fts5Index 
 ** object. Or NULL If the cursor id does not exist.
 **
-** If successful, set *pnCol to the number of indexed columns in the
-** table before returning.
+** If successful, set *ppConfig to point to the associated config object 
+** before returning.
 */
 Fts5Index *sqlite3Fts5IndexFromCsrid(
-  Fts5Global *pGlobal, 
-  i64 iCsrId, 
-  int *pnCol
+  Fts5Global *pGlobal,            /* FTS5 global context for db handle */
+  i64 iCsrId,                     /* Id of cursor to find */
+  Fts5Config **ppConfig           /* OUT: Configuration object */
 ){
   Fts5Cursor *pCsr;
   Fts5Table *pTab;
 
   pCsr = fts5CursorFromCsrid(pGlobal, iCsrId);
   pTab = (Fts5Table*)pCsr->base.pVtab;
-  *pnCol = pTab->pConfig->nCol;
+  *ppConfig = pTab->pConfig;
 
   return pTab->pIndex;
 }
index adbe526b7b22fb27bcf64ff1f240f7e66fcfa824..f47a7d3ec5cef5ec0cb289cae0dd90b97d1fc5dc 100644 (file)
@@ -55,16 +55,18 @@ struct Fts5VocabCursor {
   int bEof;                       /* True if this cursor is at EOF */
   Fts5IndexIter *pIter;           /* Term/rowid iterator object */
 
+  int nLeTerm;                    /* Size of zLeTerm in bytes */
+  char *zLeTerm;                  /* (term <= $zLeTerm) paramater, or NULL */
+
   /* These are used by 'col' tables only */
-  int nCol;
+  Fts5Config *pConfig;            /* Fts5 table configuration */
   int iCol;
   i64 *aCnt;
   i64 *aDoc;
 
-  /* Output values */
+  /* Output values used by 'row' and 'col' tables */
   i64 rowid;                      /* This table's current rowid value */
   Fts5Buffer term;                /* Current value of 'term' column */
-  i64 aVal[3];                    /* Up to three columns left of 'term' */
 };
 
 #define FTS5_VOCAB_COL    0
@@ -73,6 +75,14 @@ struct Fts5VocabCursor {
 #define FTS5_VOCAB_COL_SCHEMA  "term, col, doc, cnt"
 #define FTS5_VOCAB_ROW_SCHEMA  "term, doc, cnt"
 
+/*
+** Bits for the mask used as the idxNum value by xBestIndex/xFilter.
+*/
+#define FTS5_VOCAB_TERM_EQ 0x01
+#define FTS5_VOCAB_TERM_GE 0x02
+#define FTS5_VOCAB_TERM_LE 0x04
+
+
 /*
 ** Translate a string containing an fts5vocab table type to an 
 ** FTS5_VOCAB_XXX constant. If successful, set *peType to the output
@@ -230,6 +240,46 @@ static int fts5VocabBestIndexMethod(
   sqlite3_vtab *pVTab, 
   sqlite3_index_info *pInfo
 ){
+  int i;
+  int iTermEq = -1;
+  int iTermGe = -1;
+  int iTermLe = -1;
+  int idxNum = 0;
+  int nArg = 0;
+
+  for(i=0; i<pInfo->nConstraint; i++){
+    struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
+    if( p->usable==0 ) continue;
+    if( p->iColumn==0 ){          /* term column */
+      if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ) iTermEq = i;
+      if( p->op==SQLITE_INDEX_CONSTRAINT_LE ) iTermLe = i;
+      if( p->op==SQLITE_INDEX_CONSTRAINT_LT ) iTermLe = i;
+      if( p->op==SQLITE_INDEX_CONSTRAINT_GE ) iTermGe = i;
+      if( p->op==SQLITE_INDEX_CONSTRAINT_GT ) iTermGe = i;
+    }
+  }
+
+  if( iTermEq>=0 ){
+    idxNum |= FTS5_VOCAB_TERM_EQ;
+    pInfo->aConstraintUsage[iTermEq].argvIndex = ++nArg;
+    pInfo->aConstraintUsage[iTermEq].omit = 1;
+    pInfo->estimatedCost = 100;
+  }else{
+    pInfo->estimatedCost = 1000000;
+    if( iTermGe>=0 ){
+      idxNum |= FTS5_VOCAB_TERM_GE;
+      pInfo->aConstraintUsage[iTermGe].argvIndex = ++nArg;
+      pInfo->estimatedCost = pInfo->estimatedCost / 2;
+    }
+    if( iTermLe>=0 ){
+      idxNum |= FTS5_VOCAB_TERM_LE;
+      pInfo->aConstraintUsage[iTermLe].argvIndex = ++nArg;
+      pInfo->estimatedCost = pInfo->estimatedCost / 2;
+    }
+  }
+
+  pInfo->idxNum = idxNum;
+
   return SQLITE_OK;
 }
 
@@ -242,12 +292,11 @@ static int fts5VocabOpenMethod(
 ){
   Fts5VocabTable *pTab = (Fts5VocabTable*)pVTab;
   Fts5Index *pIndex = 0;
-  int nCol = 0;
+  Fts5Config *pConfig = 0;
   Fts5VocabCursor *pCsr = 0;
   int rc = SQLITE_OK;
   sqlite3_stmt *pStmt = 0;
   char *zSql = 0;
-  int nByte;
 
   zSql = sqlite3Fts5Mprintf(&rc,
       "SELECT t.%Q FROM %Q.%Q AS t WHERE t.%Q MATCH '*id'",
@@ -262,7 +311,7 @@ static int fts5VocabOpenMethod(
 
   if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
     i64 iId = sqlite3_column_int64(pStmt, 0);
-    pIndex = sqlite3Fts5IndexFromCsrid(pTab->pGlobal, iId, &nCol);
+    pIndex = sqlite3Fts5IndexFromCsrid(pTab->pGlobal, iId, &pConfig);
   }
 
   if( rc==SQLITE_OK && pIndex==0 ){
@@ -276,14 +325,17 @@ static int fts5VocabOpenMethod(
     }
   }
 
-  nByte = nCol * sizeof(i64) * 2 + sizeof(Fts5VocabCursor);
-  pCsr = (Fts5VocabCursor*)sqlite3Fts5MallocZero(&rc, nByte);
+  if( rc==SQLITE_OK ){
+    int nByte = pConfig->nCol * sizeof(i64) * 2 + sizeof(Fts5VocabCursor);
+    pCsr = (Fts5VocabCursor*)sqlite3Fts5MallocZero(&rc, nByte);
+  }
+
   if( pCsr ){
     pCsr->pIndex = pIndex;
     pCsr->pStmt = pStmt;
-    pCsr->nCol = nCol;
+    pCsr->pConfig = pConfig;
     pCsr->aCnt = (i64*)&pCsr[1];
-    pCsr->aDoc = &pCsr->aCnt[nCol];
+    pCsr->aDoc = &pCsr->aCnt[pConfig->nCol];
   }else{
     sqlite3_finalize(pStmt);
   }
@@ -296,6 +348,9 @@ static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
   pCsr->rowid = 0;
   sqlite3Fts5IterClose(pCsr->pIter);
   pCsr->pIter = 0;
+  sqlite3_free(pCsr->zLeTerm);
+  pCsr->nLeTerm = -1;
+  pCsr->zLeTerm = 0;
 }
 
 /*
@@ -319,16 +374,17 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
   Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
   Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
   int rc = SQLITE_OK;
+  int nCol = pCsr->pConfig->nCol;
 
   pCsr->rowid++;
 
   if( pTab->eType==FTS5_VOCAB_COL ){
-    for(pCsr->iCol++; pCsr->iCol<pCsr->nCol; pCsr->iCol++){
+    for(pCsr->iCol++; pCsr->iCol<nCol; pCsr->iCol++){
       if( pCsr->aCnt[pCsr->iCol] ) break;
     }
   }
 
-  if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=pCsr->nCol ){
+  if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=nCol ){
     if( sqlite3Fts5IterEof(pCsr->pIter) ){
       pCsr->bEof = 1;
     }else{
@@ -336,10 +392,18 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
       int nTerm;
 
       zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
+      if( pCsr->nLeTerm>=0 ){
+        int nCmp = MIN(nTerm, pCsr->nLeTerm);
+        int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp);
+        if( bCmp<0 || (bCmp==0 && pCsr->nLeTerm<nTerm) ){
+          pCsr->bEof = 1;
+          return SQLITE_OK;
+        }
+      }
+
       sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm);
-      memset(pCsr->aVal, 0, sizeof(pCsr->aVal));
-      memset(pCsr->aCnt, 0, pCsr->nCol * sizeof(i64));
-      memset(pCsr->aDoc, 0, pCsr->nCol * sizeof(i64));
+      memset(pCsr->aCnt, 0, nCol * sizeof(i64));
+      memset(pCsr->aDoc, 0, nCol * sizeof(i64));
       pCsr->iCol = 0;
 
       assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW );
@@ -353,9 +417,9 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
         if( rc==SQLITE_OK ){
           if( pTab->eType==FTS5_VOCAB_ROW ){
             while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
-              pCsr->aVal[1]++;
+              pCsr->aCnt[0]++;
             }
-            pCsr->aVal[0]++;
+            pCsr->aDoc[0]++;
           }else{
             int iCol = -1;
             while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
@@ -369,9 +433,12 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
           }
           rc = sqlite3Fts5IterNextScan(pCsr->pIter);
         }
+
         if( rc==SQLITE_OK ){
           zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
-          if( nTerm!=pCsr->term.n || memcmp(zTerm, pCsr->term.p, nTerm) ) break;
+          if( nTerm!=pCsr->term.n || memcmp(zTerm, pCsr->term.p, nTerm) ){
+            break;
+          }
           if( sqlite3Fts5IterEof(pCsr->pIter) ) break;
         }
       }
@@ -380,9 +447,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
 
   if( pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){
     while( pCsr->aCnt[pCsr->iCol]==0 ) pCsr->iCol++;
-    pCsr->aVal[0] = pCsr->iCol;
-    pCsr->aVal[1] = pCsr->aDoc[pCsr->iCol];
-    pCsr->aVal[2] = pCsr->aCnt[pCsr->iCol];
+    assert( pCsr->iCol<pCsr->pConfig->nCol );
   }
   return rc;
 }
@@ -399,10 +464,46 @@ static int fts5VocabFilterMethod(
 ){
   Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
   int rc;
-  const int flags = FTS5INDEX_QUERY_SCAN;
+
+  int iVal = 0;
+  int f = FTS5INDEX_QUERY_SCAN;
+  const char *zTerm = 0;
+  int nTerm = 0;
+
+  sqlite3_value *pEq = 0;
+  sqlite3_value *pGe = 0;
+  sqlite3_value *pLe = 0;
 
   fts5VocabResetCursor(pCsr);
-  rc = sqlite3Fts5IndexQuery(pCsr->pIndex, 0, 0, flags, 0, &pCsr->pIter);
+  if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++];
+  if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++];
+  if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++];
+
+  if( pEq ){
+    zTerm = sqlite3_value_text(pEq);
+    nTerm = sqlite3_value_bytes(pEq);
+    f = 0;
+  }else{
+    if( pGe ){
+      zTerm = sqlite3_value_text(pGe);
+      nTerm = sqlite3_value_bytes(pGe);
+    }
+    if( pLe ){
+      const char *zCopy = sqlite3_value_text(pLe);
+      pCsr->nLeTerm = sqlite3_value_bytes(pLe);
+      pCsr->zLeTerm = sqlite3_malloc(pCsr->nLeTerm+1);
+      if( pCsr->zLeTerm==0 ){
+        rc = SQLITE_NOMEM;
+      }else{
+        memcpy(pCsr->zLeTerm, zCopy, pCsr->nLeTerm+1);
+      }
+    }
+  }
+
+
+  if( rc==SQLITE_OK ){
+    rc = sqlite3Fts5IndexQuery(pCsr->pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
+  }
   if( rc==SQLITE_OK ){
     rc = fts5VocabNextMethod(pCursor);
   }
@@ -425,17 +526,29 @@ static int fts5VocabColumnMethod(
   int iCol                        /* Index of column to read value from */
 ){
   Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
-  switch( iCol ){
-    case 0: /* term */
-      sqlite3_result_text(
-          pCtx, (const char*)pCsr->term.p, pCsr->term.n, SQLITE_TRANSIENT
-      );
-      break;
 
-    default:
-      assert( iCol<4 && iCol>0 );
-      sqlite3_result_int64(pCtx, pCsr->aVal[iCol-1]);
-      break;
+  if( iCol==0 ){
+    sqlite3_result_text(
+        pCtx, (const char*)pCsr->term.p, pCsr->term.n, SQLITE_TRANSIENT
+    );
+  }
+  else if( ((Fts5VocabTable*)(pCursor->pVtab))->eType==FTS5_VOCAB_COL ){
+    assert( iCol==1 || iCol==2 || iCol==3 );
+    if( iCol==1 ){
+      const char *z = pCsr->pConfig->azCol[pCsr->iCol];
+      sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
+    }else if( iCol==2 ){
+      sqlite3_result_int64(pCtx, pCsr->aDoc[pCsr->iCol]);
+    }else{
+      sqlite3_result_int64(pCtx, pCsr->aCnt[pCsr->iCol]);
+    }
+  }else{
+    assert( iCol==1 || iCol==2 );
+    if( iCol==1 ){
+      sqlite3_result_int64(pCtx, pCsr->aDoc[0]);
+    }else{
+      sqlite3_result_int64(pCtx, pCsr->aCnt[0]);
+    }
   }
   return SQLITE_OK;
 }
index c95f50b8357e853801b00e2541dd368b516fc291..fd898d958e155dd53b190d559cb95828ccb85653 100644 (file)
@@ -56,7 +56,7 @@ do_execsql_test 1.4.1 {
 
 do_execsql_test 1.4.2 {
   SELECT * FROM v2;
-} {x 0 2 4  y 0 1 1  z 0 1 1}
+} {x one 2 4  y one 1 1  z one 1 1}
 
 do_execsql_test 1.5.1 {
   BEGIN;
@@ -67,7 +67,7 @@ do_execsql_test 1.5.1 {
 do_execsql_test 1.5.2 {
     SELECT * FROM v2 WHERE term<'d';
   COMMIT;
-} {a 0 1 1  b 0 1 1  c 0 1 1}
+} {a one 1 1  b one 1 1  c one 1 1}
 
 do_execsql_test 1.6 {
   DELETE FROM t1 WHERE one = 'a b c';
@@ -91,14 +91,14 @@ do_execsql_test 2.0 {
 }
 
 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 
-  d 0 4 6     d 1 9 13 
-  e 0 6 7     e 1 6 6 
-  f 0 9 10    f 1 7 10 
-  g 0 5 7     g 1 5 7
-  x 0 1 1     y 1 1 1
+  a a 6 11    a b 7 9
+  b a 6 7     b b 7 7 
+  c a 6 12    c b 5 8 
+  d a 4 6     d b 9 13 
+  e a 6 7     e b 6 6 
+  f a 9 10    f b 7 10 
+  g a 5 7     g b 5 7
+  x a 1 1     y b 1 1
 }
 set res_row {
   a 10 20   b 9 14   c 9 20   d 9 19   
@@ -213,5 +213,128 @@ do_catchsql_test 6.2 {
   SELECT * FROM vocab3;
 } {1 {no such fts5 table: main.lll}}
 
+#-------------------------------------------------------------------------
+# Test single term queries on fts5vocab tables (i.e. those with term=?
+# constraints in the WHERE clause).
+#
+do_execsql_test 7.0 {
+  CREATE VIRTUAL TABLE tx USING fts5(one, two);
+  INSERT INTO tx VALUES('g a ggg g a b eee',      'cc d aa ff g ee');
+  INSERT INTO tx VALUES('dd fff i a i jjj',       'f fff hh jj e f');
+  INSERT INTO tx VALUES('ggg a f f fff dd aa',    'd ggg f f j gg ddd');
+  INSERT INTO tx VALUES('e bb h jjj ii gg',       'e aa e f c fff');
+  INSERT INTO tx VALUES('j ff aa a h',            'h a j bbb bb');
+  INSERT INTO tx VALUES('cc i ff c d f',          'dd ii fff f c cc d');
+  INSERT INTO tx VALUES('jjj g i bb cc eee',      'hhh iii aaa b bbb aaa');
+  INSERT INTO tx VALUES('hhh hhh hhh bb fff f',   'fff gg aa ii h a');
+  INSERT INTO tx VALUES('b c cc aaa iii ggg f',   'iii ff ee a ff c cc');
+  INSERT INTO tx VALUES('hhh b hhh aaa j i i',    'dd ee ee aa bbb iii');
+  INSERT INTO tx VALUES('hh dd h b g ff i',       'ccc bb cc ccc f a d');
+  INSERT INTO tx VALUES('g d b ggg jj',           'fff jj ff jj g gg ee');
+  INSERT INTO tx VALUES('g ee ggg ggg cc bb eee', 'aa j jjj bbb dd eee ff');
+  INSERT INTO tx VALUES('c jjj hh ddd dd h',      'e aaa h jjj gg');
+
+  CREATE VIRTUAL TABLE txr USING fts5vocab(tx, row);
+  CREATE VIRTUAL TABLE txc USING fts5vocab(tx, col);
+}
+
+proc cont {L elem} {
+  set n 0
+  foreach e $L { if {$elem==$e} {incr n} }
+  set n
+}
+db func cont cont
+
+foreach {term} {
+  a aa aaa
+  b bb bbb
+  c cc ccc
+  d dd ddd
+  e ee eee
+  f ff fff
+  g gg ggg
+  h hh hhh
+  i ii iii
+  j jj jjj
+} {
+  set resr [db eval {
+    SELECT $term, 
+      sum(cont(one || ' ' || two, $term) > 0),
+      sum(cont(one || ' ' || two, $term))
+    FROM tx
+  }]
+  if {[lindex $resr 1]==0} {set resr [list]}
+
+  set r1 [db eval {
+    SELECT $term, 'one', sum(cont(one, $term)>0), sum(cont(one, $term)) FROM tx
+  }]
+  if {[lindex $r1 2]==0} {set r1 [list]}
+
+  set r2 [db eval {
+    SELECT $term, 'two', sum(cont(two, $term)>0), sum(cont(two, $term)) FROM tx
+  }]
+  if {[lindex $r2 2]==0} {set r2 [list]}
+
+  set resc [concat $r1 $r2]
+  do_execsql_test 7.$term.1 {SELECT * FROM txc WHERE term=$term} $resc
+  do_execsql_test 7.$term.2 {SELECT * FROM txr WHERE term=$term} $resr
+}
+
+do_execsql_test 7.1 {
+  CREATE TABLE txr_c AS SELECT * FROM txr;
+  CREATE TABLE txc_c AS SELECT * FROM txc;
+}
+
+# Test range queries on the fts5vocab tables created above.
+#
+foreach {tn a b} {
+  1   a   jjj
+  2   bb  j
+  3   ccc ddd
+  4   dd  xyz
+  5   xzy dd
+  6   h   hh
+} {
+  do_execsql_test 7.2.$tn.1 {
+    SELECT * FROM txr WHERE term>=$a
+  } [db eval {SELECT * FROM txr_c WHERE term>=$a}]
+  do_execsql_test 7.2.$tn.2 {
+    SELECT * FROM txr WHERE term<=$b
+  } [db eval {SELECT * FROM txr_c WHERE term <=$b}]
+  do_execsql_test 7.2.$tn.3 {
+    SELECT * FROM txr WHERE term>=$a AND term<=$b
+  } [db eval {SELECT * FROM txr_c WHERE term>=$a AND term <=$b}]
+
+  do_execsql_test 7.2.$tn.4 {
+    SELECT * FROM txc WHERE term>=$a
+  } [db eval {SELECT * FROM txc_c WHERE term>=$a}]
+  do_execsql_test 7.2.$tn.5 {
+    SELECT * FROM txc WHERE term<=$b
+  } [db eval {SELECT * FROM txc_c WHERE term <=$b}]
+  do_execsql_test 7.2.$tn.6 {
+    SELECT * FROM txc WHERE term>=$a AND term<=$b
+  } [db eval {SELECT * FROM txc_c WHERE term>=$a AND term <=$b}]
+
+  do_execsql_test 7.2.$tn.7 {
+    SELECT * FROM txr WHERE term>$a
+  } [db eval {SELECT * FROM txr_c WHERE term>$a}]
+  do_execsql_test 7.2.$tn.8 {
+    SELECT * FROM txr WHERE term<$b
+  } [db eval {SELECT * FROM txr_c WHERE term<$b}]
+  do_execsql_test 7.2.$tn.9 {
+    SELECT * FROM txr WHERE term>$a AND term<$b
+  } [db eval {SELECT * FROM txr_c WHERE term>$a AND term <$b}]
+
+  do_execsql_test 7.2.$tn.10 {
+    SELECT * FROM txc WHERE term>$a
+  } [db eval {SELECT * FROM txc_c WHERE term>$a}]
+  do_execsql_test 7.2.$tn.11 {
+    SELECT * FROM txc WHERE term<$b
+  } [db eval {SELECT * FROM txc_c WHERE term<$b}]
+  do_execsql_test 7.2.$tn.12 {
+    SELECT * FROM txc WHERE term>$a AND term<$b
+  } [db eval {SELECT * FROM txc_c WHERE term>$a AND term <$b}]
+}
+
 finish_test
 
index 8845573c600f129fc3cb44819d7fdb65c4c91d3d..844d674b9e1c778c8021707d5baea306a973cda5 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\scomment\sin\sexpr.c\sand\sadd\sa\sCORRUPT_DB\sto\san\sassert()\sin\sbtree.c.
-D 2015-10-16T23:55:08.882
+C Handle\sequality\sand\srange\sconstraints\son\sthe\s"term"\scolumn\sof\sfts5vocab\stables.\sAlso\shave\sthe\ssame\smodule\sreport\scolumns\susing\snames\sinstead\sof\sindexes.
+D 2015-10-17T19:49:01.860
 F Makefile.in 2ea961bc09e441874eb3d1bf7398e04feb24f3ee
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc 4eb750e0fdf52050a06d881e1b060f4bb116ed7e
@@ -103,21 +103,21 @@ F ext/fts3/unicode/mkunicode.tcl 95cf7ec186e48d4985e433ff8a1c89090a774252
 F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
 F ext/fts5/fts5.h 8b9a13b309b180e9fb88ea5666c0d8d73c6102d9
-F ext/fts5/fts5Int.h 38667e39859ff3f3bc91f47efe672023a145a118
+F ext/fts5/fts5Int.h 0332d12fdca0f4fe2231df71bd7544b3cef81122
 F ext/fts5/fts5_aux.c 1f384972d606375b8fa078319f25ab4b5feb1b35
 F ext/fts5/fts5_buffer.c 9a3aa73a4e7b26b1c805b9c92c1344ba3d19d2a8
 F ext/fts5/fts5_config.c 88a77f5d5e4dfbb2355b8f6cc9969b7f02d94685
 F ext/fts5/fts5_expr.c 28b15c9ae296204bc0a2e5cf7a667d840a9d2900
 F ext/fts5/fts5_hash.c a9d4c1efebc2a91d26ad7ebdfcbf2678ceac405f
-F ext/fts5/fts5_index.c c76d636d6cd22e3b82b1dbf3a3993447091c3bed
-F ext/fts5/fts5_main.c d3fde32e1fdd7962dc7062400d1d8c7ec2297acf
+F ext/fts5/fts5_index.c 632fdcb1971f6c9d7d6b2bd31f6c41e4189162bb
+F ext/fts5/fts5_main.c 520a29136ba07448331f73bdc36d0ffa1e9dcfef
 F ext/fts5/fts5_storage.c 9b30115742b758706de70595a8d1d084e940c978
 F ext/fts5/fts5_tcl.c 3bf445e66de32137d4693694ff7b1fd6074e32bd
 F ext/fts5/fts5_test_mi.c e96be827aa8f571031e65e481251dc1981d608bf
 F ext/fts5/fts5_tokenize.c 12c5d925286491a71bb3dad7c8924ce9cfd18320
 F ext/fts5/fts5_unicode2.c 78273fbd588d1d9bd0a7e4e0ccc9207348bae33c
 F ext/fts5/fts5_varint.c 3f86ce09cab152e3d45490d7586b7ed2e40c13f1
-F ext/fts5/fts5_vocab.c 85ebf2e93089c9d3d136cc69163370592fc040f3
+F ext/fts5/fts5_vocab.c f7c03dabb858896d42165bc54e4aa4f82650ecea
 F ext/fts5/fts5parse.y e83dca6028e3309178d05b5bd920e372dc295d35
 F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
 F ext/fts5/test/fts5_common.tcl 51f7ef3af444b89c6f6ce3896a0ac349ff4e996d
@@ -180,7 +180,7 @@ F ext/fts5/test/fts5unicode2.test c1dd890ba32b7609adba78e420faa847abe43b59
 F ext/fts5/test/fts5unicode3.test 35c3d02aa7acf7d43d8de3bfe32c15ba96e8928e
 F ext/fts5/test/fts5unindexed.test e9539d5b78c677315e7ed8ea911d4fd25437c680
 F ext/fts5/test/fts5version.test 978f59541d8cef7e8591f8be2115ec5ccb863e2e
-F ext/fts5/test/fts5vocab.test cdf97b9678484e9bad5062edf9c9106e5c3b0c5c
+F ext/fts5/test/fts5vocab.test 7dec771fd2388c11f7c336d6d155d31e12e4001a
 F ext/fts5/tool/fts5txt2db.tcl 3d19fb8ffb234031d33d7d2151acfbc55e9cfcc4
 F ext/fts5/tool/loadfts5.tcl 58e90407cc5c2b1770460119488fd7c0090d4dd3
 F ext/fts5/tool/mkfts5c.tcl 09ce6a7997440508360f5ba1651ab7e923a8bf31
@@ -1391,7 +1391,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 39e8a5d93fa370afb03223bf0c20ea0f3448b9fc
-R 7f916530a28273810e372e1a6552332a
-U drh
-Z 831fa17e60715846d1a74c0ef53a246d
+P 0df371d1a51c2028aefa4c704707773750317689
+R 97767b5f8bc213fefd21674fa8888cb4
+U dan
+Z b5428af5c06a042c6ac8c829b1afb62f
index c38b191fbed8324153bbc91904543978ce4c1ab6..6b22c8a1066a78dfacc9e389b2b2e8ff02213990 100644 (file)
@@ -1 +1 @@
-0df371d1a51c2028aefa4c704707773750317689
\ No newline at end of file
+6020d96ab47a0bebe41f691a3f44fd55d8b2d2b7
\ No newline at end of file