Begin changing fts5 to use a delete flag so that delete markers may be annihilated more quickly.

FossilOrigin-Name: 9341c070bb6140dbf559680952909674aa83fa55
This commit is contained in:
dan 2015-04-14 20:15:41 +00:00
parent 929b2cfc2e
commit f1e58b7e8d
7 changed files with 203 additions and 143 deletions

View 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;

View 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;

View 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);

View 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

View 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}

View File

@ -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

View File

@ -1 +1 @@
bdb8e82ab683f2438cde9f0b63e497dbf0141dcf
9341c070bb6140dbf559680952909674aa83fa55