]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Begin changing fts5 to use a delete flag so that delete markers may be annihilated...
authordan <dan@noemail.net>
Tue, 14 Apr 2015 20:15:41 +0000 (20:15 +0000)
committerdan <dan@noemail.net>
Tue, 14 Apr 2015 20:15:41 +0000 (20:15 +0000)
FossilOrigin-Name: 9341c070bb6140dbf559680952909674aa83fa55

ext/fts5/fts5_buffer.c
ext/fts5/fts5_hash.c
ext/fts5/fts5_index.c
ext/fts5/test/fts5aa.test
ext/fts5/test/fts5ah.test
manifest
manifest.uuid

index 73a5157ef9d63879fcdff08707cc5270525f4201..94fb4216d12371f71dd8cc4a26b45ecce20bcc57 100644 (file)
@@ -75,7 +75,7 @@ void sqlite3Fts5BufferAppendBlob(
   int nData, 
   const u8 *pData
 ){
-  assert( nData>=0 );
+  assert( *pRc || nData>=0 );
   if( sqlite3Fts5BufferGrow(pRc, pBuf, nData) ) return;
   memcpy(&pBuf->p[pBuf->n], pData, nData);
   pBuf->n += nData;
index 9a411802d5b35535f29088141c39f6c6fd3adce0..fa7701a6d0ec25993dccdde08b08892f1b34d4d4 100644 (file)
@@ -62,6 +62,7 @@ struct Fts5HashEntry {
   int nAlloc;                     /* Total size of allocation */
   int iSzPoslist;                 /* Offset of space for 4-byte poslist size */
   int nData;                      /* Total bytes of data (incl. structure) */
+  u8 bDel;                        /* Set delete-flag @ iSzPoslist */
 
   int iCol;                       /* Column of last value written */
   int iPos;                       /* Position of last value written */
@@ -167,19 +168,20 @@ static int fts5HashResize(Fts5Hash *pHash){
 
 static void fts5HashAddPoslistSize(Fts5HashEntry *p){
   if( p->iSzPoslist ){
-    /* WRITEPOSLISTSIZE */
     u8 *pPtr = (u8*)p;
-    int nSz = (p->nData - p->iSzPoslist - 1) * 2;
+    int nSz = (p->nData - p->iSzPoslist - 1);         /* Size in bytes */
+    int nPos = nSz*2 + p->bDel;                       /* Value of nPos field */
 
-    if( nSz<=127 ){
-      pPtr[p->iSzPoslist] = nSz;
+    assert( p->bDel==0 || p->bDel==1 );
+    if( nPos<=127 ){
+      pPtr[p->iSzPoslist] = nPos;
     }else{
-      int nByte = sqlite3Fts5GetVarintLen((u32)nSz);
-      /* WRITEPOSLISTSIZE */
-      memmove(&pPtr[p->iSzPoslist + nByte], &pPtr[p->iSzPoslist + 1], nSz/2);
-      sqlite3PutVarint(&pPtr[p->iSzPoslist], nSz);
+      int nByte = sqlite3Fts5GetVarintLen((u32)nPos);
+      memmove(&pPtr[p->iSzPoslist + nByte], &pPtr[p->iSzPoslist + 1], nSz);
+      sqlite3PutVarint(&pPtr[p->iSzPoslist], nPos);
       p->nData += (nByte-1);
     }
+    p->bDel = 0;
     p->iSzPoslist = 0;
   }
 }
@@ -277,6 +279,9 @@ int sqlite3Fts5HashWrite(
     /* Append the new position offset */
     p->nData += sqlite3PutVarint(&pPtr[p->nData], iPos - p->iPos + 2);
     p->iPos = iPos;
+  }else{
+    /* This is a delete. Set the delete flag. */
+    p->bDel = 1;
   }
   nIncr += p->nData;
 
index d805d256fffa18f4e1f11c580ce0359b8ae44b86..2616d32e60d6bb8054b185e7a73aab714e18729d 100644 (file)
@@ -438,7 +438,8 @@ struct Fts5MultiSegIter {
 **   Current leaf page number within segment.
 **
 ** iLeafOffset:
-**   Byte offset within the current leaf that is one byte past the end of the
+**   Byte offset within the current leaf that is the first byte of the 
+**   position list data (one byte passed the position-list size field).
 **   rowid field of the current entry. Usually this is the size field of the
 **   position list data. The exception is if the rowid for the current entry 
 **   is the last thing on the leaf page.
@@ -465,9 +466,9 @@ struct Fts5MultiSegIter {
 ** iRowidOffset/nRowidOffset/aRowidOffset:
 **     These are used if the FTS5_SEGITER_REVERSE flag is set.
 **
-**     Each time a new page is loaded, the iterator is set to point to the
-**     final rowid. Additionally, the aRowidOffset[] array is populated 
-**     with the byte offsets of all relevant rowid fields on the page. 
+**     For each rowid on the page corresponding to the current term, the
+**     corresponding aRowidOffset[] entry is set to the byte offset of the
+**     start of the "position-list-size" field within the page.
 */
 struct Fts5SegIter {
   Fts5StructureSegment *pSeg;     /* Segment to iterate through */
@@ -492,6 +493,8 @@ struct Fts5SegIter {
   /* Variables populated based on current entry. */
   Fts5Buffer term;                /* Current term */
   i64 iRowid;                     /* Current rowid */
+  int nPos;                       /* Number of bytes in current position list */
+  int bDel;                       /* True if the delete flag is set */
 };
 
 #define FTS5_SEGITER_ONETERM 0x01
@@ -722,17 +725,6 @@ static int fts5BufferCompareBlob(
   return (res==0 ? (pLeft->n - nRight) : res);
 }
 
-#if 0
-static int fts5CompareBlob(
-  const u8 *pLeft, int nLeft,
-  const u8 *pRight, int nRight
-){
-  int nCmp = MIN(nLeft, nRight);
-  int res = memcmp(pLeft, pRight, nCmp);
-  return (res==0 ? (nLeft - nRight) : res);
-}
-#endif
-
 /*
 ** Compare the contents of the two buffers using memcmp(). If one buffer
 ** is a prefix of the other, it is considered the lesser.
@@ -1555,16 +1547,64 @@ static void fts5SegIterNextPage(
   }
 }
 
+/*
+** Argument p points to a buffer containing a varint to be interpreted as a
+** position list size field. Read the varint and return the number of bytes
+** read. Before returning, set *pnSz to the number of bytes in the position
+** list, and *pbDel to true if the delete flag is set, or false otherwise.
+*/
+static int fts5GetPoslistSize(const u8 *p, int *pnSz, int *pbDel){
+  int nSz;
+  int n = fts5GetVarint32(p, nSz);
+  *pnSz = nSz/2;
+  *pbDel = nSz & 0x0001;
+  return n;
+}
+
+/*
+** Fts5SegIter.iLeafOffset currently points to the first byte of a
+** position-list size field. Read the value of the field and store it
+** in the following variables:
+**
+**   Fts5SegIter.nPos
+**   Fts5SegIter.bDel
+**
+** Leave Fts5SegIter.iLeafOffset pointing to the first byte of the 
+** position list content (if any).
+*/
+static void fts5SegIterLoadNPos(Fts5Index *p, Fts5SegIter *pIter){
+  if( p->rc==SQLITE_OK ){
+    int iOff = pIter->iLeafOffset;  /* Offset to read at */
+    if( iOff>=pIter->pLeaf->n ){
+      assert( 0 );
+      fts5SegIterNextPage(p, pIter);
+      if( pIter->pLeaf==0 ){
+        if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
+        return;
+      }
+      iOff = 4;
+    }
+    iOff += fts5GetPoslistSize(pIter->pLeaf->p+iOff, &pIter->nPos,&pIter->bDel);
+    pIter->iLeafOffset = iOff;
+  }
+}
+
 /*
 ** Fts5SegIter.iLeafOffset currently points to the first byte of the 
 ** "nSuffix" field of a term. Function parameter nKeep contains the value
 ** of the "nPrefix" field (if there was one - it is passed 0 if this is
 ** the first term in the segment).
 **
-** This function populates (Fts5SegIter.term) and (Fts5SegIter.iRowid)
-** accordingly and leaves (Fts5SegIter.iLeafOffset) set to the offset to 
-** the size field of the first position list. The position list belonging 
-** to document (Fts5SegIter.iRowid).
+** This function populates:
+**
+**   Fts5SegIter.term
+**   Fts5SegIter.rowid
+**   Fts5SegIter.nPos
+**   Fts5SegIter.bDel
+**
+** accordingly and leaves (Fts5SegIter.iLeafOffset) set to the content of
+** the first position list. The position list belonging to document 
+** (Fts5SegIter.iRowid).
 */
 static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){
   u8 *a = pIter->pLeaf->p;        /* Buffer to read data from */
@@ -1626,6 +1666,7 @@ static void fts5SegIterInit(
     u8 *a = pIter->pLeaf->p;
     pIter->iLeafOffset = fts5GetU16(&a[2]);
     fts5SegIterLoadTerm(p, pIter, 0);
+    fts5SegIterLoadNPos(p, pIter);
   }
 }
 
@@ -1633,10 +1674,16 @@ static void fts5SegIterInit(
 ** This function is only ever called on iterators created by calls to
 ** Fts5IndexQuery() with the FTS5INDEX_QUERY_DESC flag set.
 **
-** When this function is called, iterator pIter points to the first rowid
-** on the current leaf associated with the term being queried. This function
-** advances it to point to the last such rowid and, if necessary, initializes
-** the aRowidOffset[] and iRowidOffset variables.
+** The iterator is in an unusual state when this function is called: the
+** Fts5SegIter.iLeafOffset variable is set to the offset of the start of
+** the position-list size field for the first relevant rowid on the page.
+** Fts5SegIter.rowid is set, but nPos and bDel are not.
+**
+** This function advances the iterator so that it points to the last 
+** relevant rowid on the page and, if necessary, initializes the 
+** aRowidOffset[] and iRowidOffset variables. At this point the iterator
+** is in its regular state - Fts5SegIter.iLeafOffset points to the first
+** byte of the position list content associated with said rowid.
 */
 static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
   int n = pIter->pLeaf->n;
@@ -1647,10 +1694,10 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
   while( p->rc==SQLITE_OK && i<n ){
     i64 iDelta = 0;
     int nPos;
+    int bDummy;
 
-    /* READPOSLISTSIZE */
-    i += fts5GetVarint32(&a[i], nPos);
-    i += nPos / 2;
+    i += fts5GetPoslistSize(&a[i], &nPos, &bDummy);
+    i += nPos;
     if( i>=n ) break;
     i += getVarint(&a[i], (u64*)&iDelta);
     if( iDelta==0 ) break;
@@ -1671,6 +1718,7 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
     pIter->iLeafOffset = i;
   }
   pIter->iRowidOffset = iRowidOffset;
+  fts5SegIterLoadNPos(p, pIter);
 }
 
 /*
@@ -1730,17 +1778,21 @@ static int fts5SegIterIsDelete(
   int bRet = 0;
   Fts5Data *pLeaf = pIter->pLeaf;
   if( p->rc==SQLITE_OK && pLeaf ){
+    bRet = pIter->nPos==0;
+    /* bRet = pIter->bDel; */
+#if 0
     if( pIter->iLeafOffset<pLeaf->n ){
-      bRet = (pLeaf->p[pIter->iLeafOffset]==0x00);
+      bRet = ((pLeaf->p[pIter->iLeafOffset] & 0xFE)==0x00);
     }else{
       Fts5Data *pNew = fts5DataRead(p, FTS5_SEGMENT_ROWID(
             pIter->iIdx, pIter->pSeg->iSegid, 0, pIter->iLeafPgno+1
       ));
       if( pNew ){
-        bRet = (pNew->p[4]==0x00);
+        bRet = ((pNew->p[4] & 0xFE)==0x00);
         fts5DataRelease(pNew);
       }
     }
+#endif
   }
   return bRet;
 }
@@ -1760,19 +1812,23 @@ static void fts5SegIterNext(
   assert( pbNewTerm==0 || *pbNewTerm==0 );
   if( p->rc==SQLITE_OK ){
     if( pIter->flags & FTS5_SEGITER_REVERSE ){
+
       if( pIter->iRowidOffset>0 ){
         u8 *a = pIter->pLeaf->p;
         int iOff;
         int nPos;
+        int bDummy;
         i64 iDelta;
-        pIter->iRowidOffset--;
 
-        pIter->iLeafOffset = iOff = pIter->aRowidOffset[pIter->iRowidOffset];
-        /* READPOSLISTSIZE */
-        iOff += fts5GetVarint32(&a[iOff], nPos);
-        iOff += (nPos / 2);
-        getVarint(&a[iOff], (u64*)&iDelta);
-        pIter->iRowid -= iDelta;
+        if( p->rc==SQLITE_OK ){
+          pIter->iRowidOffset--;
+          pIter->iLeafOffset = iOff = pIter->aRowidOffset[pIter->iRowidOffset];
+          iOff += fts5GetPoslistSize(&a[iOff], &nPos, &bDummy);
+          iOff += nPos;
+          getVarint(&a[iOff], (u64*)&iDelta);
+          pIter->iRowid -= iDelta;
+          fts5SegIterLoadNPos(p, pIter);
+        }
       }else{
         fts5SegIterReverseNewPage(p, pIter);
       }
@@ -1786,13 +1842,7 @@ static void fts5SegIterNext(
       u8 *a = pLeaf->p;
       int n = pLeaf->n;
 
-      iOff = pIter->iLeafOffset;
-      if( iOff<n ){
-        int nPoslist;
-        /* READPOSLISTSIZE */
-        iOff += fts5GetVarint32(&a[iOff], nPoslist);
-        iOff += nPoslist / 2;
-      }
+      iOff = pIter->iLeafOffset + pIter->nPos;
 
       if( iOff<n ){
         /* The next entry is on the current page */
@@ -1826,10 +1876,6 @@ static void fts5SegIterNext(
           pIter->pLeaf->n = nList;
           sqlite3Fts5BufferSet(&p->rc, &pIter->term, strlen(zTerm), (u8*)zTerm);
           pIter->iLeafOffset = getVarint(pList, (u64*)&pIter->iRowid);
-          if( pIter->flags & FTS5_SEGITER_REVERSE ){
-            assert( 0 );
-            fts5SegIterReverseInitPage(p, pIter);
-          }
         }
       }else{
         iOff = 0;
@@ -1850,46 +1896,60 @@ static void fts5SegIterNext(
       }
 
       /* Check if the iterator is now at EOF. If so, return early. */
-      if( pIter->pLeaf && bNewTerm ){
-        if( pIter->flags & FTS5_SEGITER_ONETERM ){
-          fts5DataRelease(pIter->pLeaf);
-          pIter->pLeaf = 0;
+      if( pIter->pLeaf ){
+        if( bNewTerm ){
+          if( pIter->flags & FTS5_SEGITER_ONETERM ){
+            fts5DataRelease(pIter->pLeaf);
+            pIter->pLeaf = 0;
+          }else{
+            fts5SegIterLoadTerm(p, pIter, nKeep);
+            fts5SegIterLoadNPos(p, pIter);
+            if( pbNewTerm ) *pbNewTerm = 1;
+          }
         }else{
-          fts5SegIterLoadTerm(p, pIter, nKeep);
-          if( pbNewTerm ) *pbNewTerm = 1;
+          fts5SegIterLoadNPos(p, pIter);
         }
       }
     }
   }
 }
 
+#define SWAPVAL(T, a, b) { T tmp; tmp=a; a=b; b=tmp; }
+
 /*
 ** Iterator pIter currently points to the first rowid in a doclist. This
 ** function sets the iterator up so that iterates in reverse order through
 ** the doclist.
 */
 static void fts5SegIterReverse(Fts5Index *p, int iIdx, Fts5SegIter *pIter){
-  Fts5Data *pLeaf;                /* Current leaf data */
-  int iOff = pIter->iLeafOffset;  /* Byte offset within current leaf */
   Fts5Data *pLast = 0;
   int pgnoLast = 0;
 
-  /* Move to the page that contains the last rowid in this doclist. */
-  pLeaf = pIter->pLeaf;
-
   if( pIter->pDlidx ){
     int iSegid = pIter->pSeg->iSegid;
     pgnoLast = pIter->pDlidx->iLeafPgno;
     pLast = fts5DataRead(p, FTS5_SEGMENT_ROWID(iIdx, iSegid, 0, pgnoLast));
   }else{
+    int iOff;                               /* Byte offset within pLeaf */
+    Fts5Data *pLeaf = pIter->pLeaf;         /* Current leaf data */
+
+    /* Currently, Fts5SegIter.iLeafOffset (and iOff) points to the first 
+    ** byte of position-list content for the current rowid. Back it up
+    ** so that it points to the start of the position-list size field. */
+    pIter->iLeafOffset -= sqlite3Fts5GetVarintLen(pIter->nPos*2 + pIter->bDel);
+    iOff = pIter->iLeafOffset;
+    assert( iOff>=4 );
+
+    /* Search for a new term within the current leaf. If one can be found,
+    ** then this page contains the largest rowid for the current term. */
     while( iOff<pLeaf->n ){
       int nPos;
       i64 iDelta;
+      int bDummy;
 
-      /* Position list size in bytes */
-      /* READPOSLISTSIZE */
-      iOff += fts5GetVarint32(&pLeaf->p[iOff], nPos);
-      iOff += (nPos / 2);
+      /* Read the position-list size field */
+      iOff += fts5GetPoslistSize(&pLeaf->p[iOff], &nPos, &bDummy);
+      iOff += nPos;
       if( iOff>=pLeaf->n ) break;
 
       /* Rowid delta. Or, if 0x00, the end of doclist marker. */
@@ -1898,28 +1958,27 @@ static void fts5SegIterReverse(Fts5Index *p, int iIdx, Fts5SegIter *pIter){
       iOff += nPos;
     }
 
+    /* If this condition is true then the largest rowid for the current
+    ** term may not be stored on the current page. So search forward to
+    ** see where said rowid really is.  */
     if( iOff>=pLeaf->n ){
+      int pgno;
       Fts5StructureSegment *pSeg = pIter->pSeg;
-      i64 iAbs = FTS5_SEGMENT_ROWID(iIdx, pSeg->iSegid, 0, pIter->iLeafPgno);
-      i64 iLast = FTS5_SEGMENT_ROWID(iIdx, pSeg->iSegid, 0, pSeg->pgnoLast);
 
       /* The last rowid in the doclist may not be on the current page. Search
-       ** forward to find the page containing the last rowid.  */
-      for(iAbs++; p->rc==SQLITE_OK && iAbs<=iLast; iAbs++){
+      ** forward to find the page containing the last rowid.  */
+      for(pgno=pIter->iLeafPgno+1; !p->rc && pgno<=pSeg->pgnoLast; pgno++){
+        i64 iAbs = FTS5_SEGMENT_ROWID(iIdx, pSeg->iSegid, 0, pgno);
         Fts5Data *pNew = fts5DataRead(p, iAbs);
         if( pNew ){
           int iRowid, iTerm;
           fts5LeafHeader(pNew, &iRowid, &iTerm);
           if( iRowid ){
-            Fts5Data *pTmp = pLast;
-            pLast = pNew;
-            pNew = pTmp;
-            pgnoLast = iAbs & (((i64)1 << FTS5_DATA_PAGE_B) - 1);
-          }
-          if( iTerm ){
-            iAbs = iLast;
+            SWAPVAL(Fts5Data*, pNew, pLast);
+            pgnoLast = pgno;
           }
           fts5DataRelease(pNew);
+          if( iTerm ) break;
         }
       }
     }
@@ -1927,14 +1986,16 @@ static void fts5SegIterReverse(Fts5Index *p, int iIdx, Fts5SegIter *pIter){
 
   /* If pLast is NULL at this point, then the last rowid for this doclist
   ** lies on the page currently indicated by the iterator. In this case 
-  ** iLastOff is set to the value that pIter->iLeafOffset will take when
-  ** the iterator points to that rowid.
+  ** pIter->iLeafOffset is already set to point to the position-list size
+  ** field associated with the first relevant rowid on the page.
   **
   ** Or, if pLast is non-NULL, then it is the page that contains the last
-  ** rowid.
+  ** rowid. In this case configure the iterator so that it points to the
+  ** first rowid on this page.
   */
   if( pLast ){
     int dummy;
+    int iOff;
     fts5DataRelease(pIter->pLeaf);
     pIter->pLeaf = pLast;
     pIter->iLeafPgno = pgnoLast;
@@ -1966,18 +2027,18 @@ static void fts5SegIterLoadDlidx(Fts5Index *p, int iIdx, Fts5SegIter *pIter){
   ** early without loading the doclist-index (as it belongs to a different
   ** term. */
   if( pIter->iTermLeafPgno==pIter->iLeafPgno ){
+    int nPos = pIter->nPos;
     while( iOff<pLeaf->n ){
       i64 iDelta;
-      int nPoslist;
 
-      /* iOff is currently the offset of the size field of a position list. */
-      /* READPOSLISTSIZE */
-      iOff += fts5GetVarint32(&pLeaf->p[iOff], nPoslist);
-      iOff += nPoslist / 2;
+      /* iOff is currently the offset of the start of position list data */
+      iOff += nPos;
+      iOff += getVarint(&pLeaf->p[iOff], (u64*)&iDelta);
+      if( iDelta==0 ) return;
 
       if( iOff<pLeaf->n ){
-        iOff += getVarint(&pLeaf->p[iOff], (u64*)&iDelta);
-        if( iDelta==0 ) return;
+        int bDummy;
+        iOff += fts5GetPoslistSize(&pLeaf->p[iOff], &nPos, &bDummy);
       }
     }
   }
@@ -2048,6 +2109,7 @@ static void fts5SegIterSeekInit(
     int res;
     pIter->iLeafOffset = fts5GetU16(&pIter->pLeaf->p[2]);
     fts5SegIterLoadTerm(p, pIter, 0);
+    fts5SegIterLoadNPos(p, pIter);
     do {
       res = fts5BufferCompareBlob(&pIter->term, pTerm, nTerm);
       if( res>=0 ) break;
@@ -2126,6 +2188,8 @@ static void fts5SegIterHashInit(
     if( flags & FTS5INDEX_QUERY_DESC ){
       pIter->flags |= FTS5_SEGITER_REVERSE;
       fts5SegIterReverseInitPage(p, pIter);
+    }else{
+      fts5SegIterLoadNPos(p, pIter);
     }
   }
 }
@@ -2296,6 +2360,7 @@ static void fts5SegIterGotoPage(
     }else{
       iOff += getVarint(&a[iOff], (u64*)&pIter->iRowid);
       pIter->iLeafOffset = iOff;
+      fts5SegIterLoadNPos(p, pIter);
     }
   }
 }
@@ -2470,7 +2535,7 @@ static void fts5MultiIterNew(
   Fts5Structure *pStruct,         /* Structure of specific index */
   int iIdx,                       /* Config.aHash[] index of FTS index */
   int bSkipEmpty,                 /* True to ignore delete-keys */
-  int flags,                      /* True for >= */
+  int flags,                      /* FTS5INDEX_QUERY_XXX flags */
   const u8 *pTerm, int nTerm,     /* Term to seek to (or NULL/0) */
   int iLevel,                     /* Level to iterate (-1 for all) */
   int nSegment,                   /* Number of segments to merge (iLevel>=0) */
@@ -2653,23 +2718,11 @@ static void fts5ChunkIterInit(
     pIter->iLeafRowid = rowid;
   }
 
-  if( iOff<pLeaf->n ){
-    fts5DataReference(pLeaf);
-    pIter->pLeaf = pLeaf;
-  }else{
-    pIter->nRem = 1;
-    fts5ChunkIterNext(p, pIter);
-    if( p->rc ) return;
-    iOff = 4;
-    pLeaf = pIter->pLeaf;
-  }
-
-  /* READPOSLISTSIZE */
-  iOff += fts5GetVarint32(&pLeaf->p[iOff], pIter->nRem);
-  pIter->nRem = pIter->nRem / 2;
+  fts5DataReference(pLeaf);
+  pIter->pLeaf = pLeaf;
+  pIter->nRem = pSeg->nPos;
   pIter->n = MIN(pLeaf->n - iOff, pIter->nRem);
   pIter->p = pLeaf->p + iOff;
-
   if( pIter->n==0 ){
     fts5ChunkIterNext(p, pIter);
   }
@@ -3047,12 +3100,13 @@ static void fts5WriteAppendTerm(
 }
 
 /*
-** Append a docid to the writers output. 
+** Append a docid and position-list size field to the writers output. 
 */
 static void fts5WriteAppendRowid(
   Fts5Index *p, 
   Fts5SegWriter *pWriter,
-  i64 iRowid
+  i64 iRowid,
+  int nPos
 ){
   if( p->rc==SQLITE_OK ){
     Fts5PageWriter *pPage = &pWriter->aWriter[0];
@@ -3076,6 +3130,8 @@ static void fts5WriteAppendRowid(
     pWriter->bFirstRowidInDoclist = 0;
     pWriter->bFirstRowidInPage = 0;
 
+    fts5BufferAppendVarint(&p->rc, &pPage->buf, nPos);
+
     if( pPage->buf.n>=p->pConfig->pgsz ){
       fts5WriteFlushLeaf(p, pWriter);
       pWriter->bFirstRowidInPage = 1;
@@ -3376,11 +3432,9 @@ fflush(stdout);
       }
 
       /* Append the rowid to the output */
-      fts5WriteAppendRowid(p, &writer, fts5MultiIterRowid(pIter));
-
-      /* Copy the position list from input to output */
       /* WRITEPOSLISTSIZE */
-      fts5WriteAppendPoslistInt(p, &writer, sPos.nRem * 2);
+      fts5WriteAppendRowid(p, &writer, fts5MultiIterRowid(pIter), sPos.nRem*2);
+
       for(/* noop */; !fts5ChunkIterEof(p, &sPos); fts5ChunkIterNext(p, &sPos)){
         fts5WriteAppendPoslistData(p, &writer, sPos.p, sPos.n);
       }
@@ -3530,9 +3584,10 @@ struct Fts5FlushCtx {
 ** list nMax bytes or less in size.
 */
 static int fts5PoslistPrefix(const u8 *aBuf, int nMax){
-  int ret = 0;
+  int ret;
+  u32 dummy;
+  ret = fts5GetVarint32(aBuf, dummy);
   while( 1 ){
-    u32 dummy;
     int i = fts5GetVarint32(&aBuf[ret], dummy);
     if( (ret + i) > nMax ) break;
     ret += i;
@@ -3641,12 +3696,12 @@ static void fts5FlushOneHash(Fts5Index *p, int iHash, int *pnLeaf){
         ** loop iterates through the poslists that make up the current 
         ** doclist.  */
         while( iOff<nDoclist ){
-          u32 nPos;
+          int nPos;
           int nCopy;
+          int bDummy;
           iOff += getVarint(&pDoclist[iOff], (u64*)&iDelta);
-          /* READPOSLISTSIZE */
-          nCopy = fts5GetVarint32(&pDoclist[iOff], nPos);
-          nCopy += (nPos / 2);
+          nCopy = fts5GetPoslistSize(&pDoclist[iOff], &nPos, &bDummy);
+          nCopy += nPos;
           iRowid += iDelta;
           
           if( bFirstDocid ){
@@ -3670,12 +3725,13 @@ static void fts5FlushOneHash(Fts5Index *p, int iHash, int *pnLeaf){
             int iPos = 0;
             while( 1 ){
               int nSpace = pgsz - pBuf->n;
-              int n;
+              int n = 0;
               if( (nCopy - iPos)<=nSpace ){
                 n = nCopy - iPos;
               }else{
                 n = fts5PoslistPrefix(&pPoslist[iPos], nSpace);
               }
+              assert( n>0 );
               fts5BufferSafeAppendBlob(pBuf, &pPoslist[iPos], n);
               iPos += n;
               if( iPos>=nCopy ) break;
@@ -3684,7 +3740,6 @@ static void fts5FlushOneHash(Fts5Index *p, int iHash, int *pnLeaf){
             }
             bFirstDocid = 1;
           }
-          assert( pBuf->n<=pgsz );
           iOff += nCopy;
         }
       }
@@ -4097,6 +4152,7 @@ static void fts5MultiIterPoslist(
 
 static void fts5DoclistIterNext(Fts5DoclistIter *pIter){
   if( pIter->i<pIter->n ){
+    int bDummy;
     if( pIter->i ){
       i64 iDelta;
       pIter->i += getVarint(&pIter->a[pIter->i], (u64*)&iDelta);
@@ -4108,9 +4164,9 @@ static void fts5DoclistIterNext(Fts5DoclistIter *pIter){
     }else{
       pIter->i += getVarint(&pIter->a[pIter->i], (u64*)&pIter->iRowid);
     }
-    /* READPOSLISTSIZE */
-    pIter->i += fts5GetVarint32(&pIter->a[pIter->i], pIter->nPoslist);
-    pIter->nPoslist = pIter->nPoslist / 2;
+    pIter->i += fts5GetPoslistSize(
+        &pIter->a[pIter->i], &pIter->nPoslist, &bDummy
+    );
     pIter->aPoslist = &pIter->a[pIter->i];
     pIter->i += pIter->nPoslist;
   }else{
@@ -4175,7 +4231,7 @@ static void fts5MergePrefixLists(
 
     fts5DoclistIterInit(p1, bDesc, &i1);
     fts5DoclistIterInit(p2, bDesc, &i2);
-    while( i1.aPoslist!=0 || i2.aPoslist!=0 ){
+    while( p->rc==SQLITE_OK && (i1.aPoslist!=0 || i2.aPoslist!=0) ){
       if( i2.aPoslist==0 || (i1.aPoslist && 
            ( (bDesc && i1.iRowid>i2.iRowid) || (!bDesc && i1.iRowid<i2.iRowid) )
       )){
@@ -4436,6 +4492,8 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){
         ** the index is disabled are the same. In both ASC and DESC order. */
         if( iIdx>0 && rc==SQLITE_OK ){
           int f = flags|FTS5INDEX_QUERY_TEST_NOIDX;
+static int nCall = 0;
+nCall++;
           ck2 = 0;
           rc = fts5QueryCksum(p, z, n, f, &ck2);
           if( rc==SQLITE_OK && ck1!=ck2 ) rc = FTS5_CORRUPT;
@@ -5072,9 +5130,9 @@ static int fts5DecodeDoclist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){
   }
   while( iOff<n ){
     int nPos;
-    /* READPOSLISTSIZE */
-    iOff += fts5GetVarint32(&a[iOff], nPos);
-    iOff += fts5DecodePoslist(pRc, pBuf, &a[iOff], MIN(n-iOff, nPos / 2));
+    int bDummy;
+    iOff += fts5GetPoslistSize(&a[iOff], &nPos, &bDummy);
+    iOff += fts5DecodePoslist(pRc, pBuf, &a[iOff], MIN(n-iOff, nPos));
     if( iOff<n ){
       i64 iDelta;
       iOff += sqlite3GetVarint(&a[iOff], (u64*)&iDelta);
index af4656a82b1cb0b38de5db135a585f32ce634b06..24a35211521d5e981e8768242340ef15b17bfe27 100644 (file)
@@ -21,8 +21,6 @@ ifcapable !fts5 {
   return
 }
 
-if 1 {
-
 do_execsql_test 1.0 {
   CREATE VIRTUAL TABLE t1 USING fts5(a, b, c);
   SELECT name, sql FROM sqlite_master;
@@ -329,7 +327,6 @@ do_execsql_test 13.6 {
   SELECT rowid FROM t1 WHERE t1 MATCH '.';
 } {}
 
-}
 #-------------------------------------------------------------------------
 #
 reset_db
index 3b05f67e96bcb15ab411e45c6aefb032ec298ac8..1ee4ab123ea31d652ba03ff8749959963da0070f 100644 (file)
@@ -94,7 +94,7 @@ foreach {tn q res} "
   } {1}
 
   do_test 1.6.$tn.2 {
-    set n [execsql_reads "$q ORDER BY rowid ASC"]
+    set n [execsql_reads "$q ORDER BY rowid DESC"]
     expr {$n < ($nReadX / 10)}
   } {1}
 
index a1dc46526cb040d0497183bb07b387fd79a35453..5066aafec8cf7b897359f09db7825215bcd051c6 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Have\sfts5\sintegrity\scheck\sverify\sthat\sprefix\sindexes\scontain\sthe\ssame\svalues\sas\sreturned\sby\sprefix\squeries\son\sthe\smain\sterms\sindex.
-D 2015-04-11T18:25:04.731
+C Begin\schanging\sfts5\sto\suse\sa\sdelete\sflag\sso\sthat\sdelete\smarkers\smay\sbe\sannihilated\smore\squickly.
+D 2015-04-14T20:15:41.831
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 88a3e6261286db378fdffa1124cad11b3c05f5bb
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -108,11 +108,11 @@ F ext/fts5/fts5.c 1eb8ca073be5222c43e4eee5408764c2cbb4200b
 F ext/fts5/fts5.h 24a2cc35b5e76eec57b37ba48c12d9d2cb522b3a
 F ext/fts5/fts5Int.h 1b537736f8838df7fca10245c0f70a23cfddc7f5
 F ext/fts5/fts5_aux.c fcea18b1a2a3f95a498b52aba2983557d7678a22
-F ext/fts5/fts5_buffer.c 29f79841bf6eef5220eef41b122419b1bcb07b06
+F ext/fts5/fts5_buffer.c 3ba56cc6824c9f7b1e0695159e0a9c636f6b4a23
 F ext/fts5/fts5_config.c 0847facc8914f57ea4452c43ce109200dc65e894
 F ext/fts5/fts5_expr.c 5215137efab527577d36bdf9e44bfc2ec3e1be98
-F ext/fts5/fts5_hash.c 7c134ed05d25e2a19418356d78aa4e7059bd319c
-F ext/fts5/fts5_index.c 670a428c51abb4f5f3f6135cc9fd0a19c192f96d
+F ext/fts5/fts5_hash.c 3cb5a3d04dd2030eb0ac8d544711dfd37c0e6529
+F ext/fts5/fts5_index.c ba7680d0c6b3f4772e1ac54676f6f65679c24a08
 F ext/fts5/fts5_storage.c ac0f0937059c8d4f38a1f13aa5f2c2cd7edf3e0d
 F ext/fts5/fts5_tcl.c 617b6bb96545be8d9045de6967c688cd9cd15541
 F ext/fts5/fts5_tokenize.c c07f2c2f749282c1dbbf46bde1f6d7095c740b8b
@@ -120,14 +120,14 @@ F ext/fts5/fts5_unicode2.c f74f53316377068812a1fa5a37819e6b8124631d
 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 065767c60ad301f77ad95f24369305e13347aa00
+F ext/fts5/test/fts5aa.test 91f22b3cc7b372a2903c828e907a1e52f1177b8a
 F ext/fts5/test/fts5ab.test 5da2e92a8047860b9e22b6fd3990549639d631b1
 F ext/fts5/test/fts5ac.test 8b3c2938840da8f3f6a53b1324fb03e0bac12d1e
 F ext/fts5/test/fts5ad.test 2141b0360dc4397bfed30f0b0d700fa64b44835d
 F ext/fts5/test/fts5ae.test 9175201baf8c885fc1cbb2da11a0c61fd11224db
 F ext/fts5/test/fts5af.test c2501ec2b61d6b179c305f5d2b8782ab3d4f832a
 F ext/fts5/test/fts5ag.test ec3e119b728196620a31507ef503c455a7a73505
-F ext/fts5/test/fts5ah.test 56b5a2599707621bf2fd1b5a00ddc0c0c1ffbf06
+F ext/fts5/test/fts5ah.test d74cf8b7de5b8424f732acef69fe12122a12f2bf
 F ext/fts5/test/fts5ai.test f20e53bbf0c55bc596f1fd47f2740dae028b8f37
 F ext/fts5/test/fts5aj.test 05b569f5c16ea3098fb1984eec5cf50dbdaae5d8
 F ext/fts5/test/fts5ak.test 7b8c5df96df599293f920b7e5521ebc79f647592
@@ -1292,7 +1292,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 49c1e74522a26e5dbe6f8305bc96487279b80dfb
-R 008cbeef4b71700e108cdf2aad4130b5
+P bdb8e82ab683f2438cde9f0b63e497dbf0141dcf
+R 98bc774fac6611e41c6e4422cb947fd5
 U dan
-Z b886f5faefd1f02721c5ad30d158df62
+Z 5d35832a61b13dbbe8195fefbe4221a8
index 5a159d131f46976688af8386d8d6a767a59fdccd..0a948972b3d0ec1c89e62d70b17070403e5ecacd 100644 (file)
@@ -1 +1 @@
-bdb8e82ab683f2438cde9f0b63e497dbf0141dcf
\ No newline at end of file
+9341c070bb6140dbf559680952909674aa83fa55
\ No newline at end of file