mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Use doclist-indexes with "ORDER BY rowid ASC" fts5 queries as well.
FossilOrigin-Name: d028ba6589f3122b635474c2683c0f93d5bc6c7c
This commit is contained in:
@ -550,18 +550,23 @@ struct Fts5NodeIter {
|
||||
** of a doclist-index record.
|
||||
**
|
||||
** pData:
|
||||
** A reference to the dlidx record.
|
||||
** Record containing the doclist-index data.
|
||||
**
|
||||
** bEof:
|
||||
** Set to true once iterator has reached EOF.
|
||||
**
|
||||
** iOff:
|
||||
** Set to the current offset within record pData.
|
||||
*/
|
||||
struct Fts5DlidxIter {
|
||||
Fts5Data *pData; /* Data for doclist index, if any */
|
||||
int iOff; /* Current offset into pDlidx */
|
||||
int bRowidValid; /* iRowid is valid */
|
||||
int bEof; /* At EOF already */
|
||||
int iFirstOff; /* Used by reverse iterators only */
|
||||
|
||||
/* Output variables */
|
||||
int iLeafPgno; /* Page number of current leaf page */
|
||||
int bZero; /* True if current leaf has no rowids */
|
||||
i64 iRowid; /* If bZero==0, first rowid on leaf */
|
||||
i64 iRowid; /* First rowid on leaf iLeafPgno */
|
||||
};
|
||||
|
||||
|
||||
@ -1124,14 +1129,83 @@ static void fts5NodeIterFree(Fts5NodeIter *pIter){
|
||||
}
|
||||
|
||||
/*
|
||||
** Return non-zero if EOF is reached.
|
||||
** The iterator passed as the first argument has the following fields set
|
||||
** as follows. This function sets up the rest of the iterator so that it
|
||||
** points to the first rowid in the doclist-index.
|
||||
**
|
||||
** pData: pointer to doclist-index record,
|
||||
** iLeafPgno: page number that this doclist-index is associated with.
|
||||
*/
|
||||
static int fts5DlidxIterNext(Fts5DlidxIter *pIter, int bRev){
|
||||
if( bRev ){
|
||||
static int fts5DlidxIterFirst(Fts5DlidxIter *pIter){
|
||||
Fts5Data *pData = pIter->pData;
|
||||
int i;
|
||||
|
||||
assert( pIter->pData );
|
||||
assert( pIter->iLeafPgno>0 );
|
||||
|
||||
/* Count the number of leading 0x00 bytes. Then set iLeafPgno. */
|
||||
for(i=0; i<pData->n; i++){
|
||||
if( pData->p[i] ) break;
|
||||
}
|
||||
pIter->iLeafPgno += (i+1);
|
||||
pIter->iOff = i;
|
||||
|
||||
/* Unless we are already at the end of the doclist-index, load the first
|
||||
** rowid value. */
|
||||
if( pIter->iOff<pData->n ){
|
||||
pIter->iOff += getVarint(&pData->p[pIter->iOff], (u64*)&pIter->iRowid);
|
||||
}else{
|
||||
pIter->bEof = 1;
|
||||
}
|
||||
pIter->iFirstOff = pIter->iOff;
|
||||
return pIter->bEof;
|
||||
}
|
||||
|
||||
/*
|
||||
** Advance the iterator passed as the only argument.
|
||||
*/
|
||||
static int fts5DlidxIterNext(Fts5DlidxIter *pIter){
|
||||
Fts5Data *pData = pIter->pData;
|
||||
int iOff;
|
||||
|
||||
for(iOff=pIter->iOff; iOff<pData->n; iOff++){
|
||||
if( pData->p[iOff] ) break;
|
||||
}
|
||||
|
||||
if( iOff<pData->n ){
|
||||
i64 iVal;
|
||||
int iOff = pIter->iOff;
|
||||
int iLimit;
|
||||
pIter->iLeafPgno += (iOff - pIter->iOff) + 1;
|
||||
iOff += getVarint(&pData->p[iOff], (u64*)&iVal);
|
||||
pIter->iRowid -= iVal;
|
||||
pIter->iOff = iOff;
|
||||
}else{
|
||||
pIter->bEof = 1;
|
||||
}
|
||||
|
||||
return pIter->bEof;
|
||||
}
|
||||
|
||||
static int fts5DlidxIterEof(Fts5Index *p, Fts5DlidxIter *pIter){
|
||||
return (p->rc!=SQLITE_OK || pIter->bEof);
|
||||
}
|
||||
|
||||
static void fts5DlidxIterLast(Fts5DlidxIter *pIter){
|
||||
if( fts5DlidxIterFirst(pIter)==0 ){
|
||||
while( 0==fts5DlidxIterNext(pIter) );
|
||||
pIter->bEof = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int fts5DlidxIterPrev(Fts5DlidxIter *pIter){
|
||||
int iOff = pIter->iOff;
|
||||
|
||||
assert( pIter->bEof==0 );
|
||||
if( iOff<=pIter->iFirstOff ){
|
||||
pIter->bEof = 1;
|
||||
}else{
|
||||
u8 *a = pIter->pData->p;
|
||||
i64 iVal;
|
||||
int iLimit;
|
||||
|
||||
/* Currently iOff points to the first byte of a varint. This block
|
||||
** decrements iOff until it points to the first byte of the previous
|
||||
@ -1141,53 +1215,19 @@ static int fts5DlidxIterNext(Fts5DlidxIter *pIter, int bRev){
|
||||
for(iOff--; iOff>iLimit; iOff--){
|
||||
if( (a[iOff-1] & 0x80)==0 ) break;
|
||||
}
|
||||
pIter->iOff = iOff;
|
||||
|
||||
if( iOff<=0 ){
|
||||
pIter->bEof = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
getVarint(&a[iOff], (u64*)&iVal);
|
||||
if( iVal==0 ){
|
||||
pIter->bZero = 1;
|
||||
}else if( iOff==0 ){
|
||||
pIter->iRowid = iVal;
|
||||
}else{
|
||||
pIter->iRowid += iVal;
|
||||
}
|
||||
pIter->iRowid += iVal;
|
||||
pIter->iLeafPgno--;
|
||||
}else{
|
||||
i64 iVal;
|
||||
if( pIter->iOff>=pIter->pData->n ){
|
||||
pIter->bEof = 1;
|
||||
return 1;
|
||||
|
||||
while( a[iOff-1]==0x00 ){
|
||||
iOff--;
|
||||
pIter->iLeafPgno--;
|
||||
}
|
||||
pIter->iOff += getVarint(&pIter->pData->p[pIter->iOff], (u64*)&iVal);
|
||||
if( iVal==0 ){
|
||||
pIter->bZero = 1;
|
||||
}else{
|
||||
pIter->bZero = 0;
|
||||
if( pIter->bRowidValid ){
|
||||
pIter->iRowid -= iVal;
|
||||
}else{
|
||||
pIter->bRowidValid = 1;
|
||||
pIter->iRowid = iVal;
|
||||
}
|
||||
}
|
||||
pIter->iLeafPgno++;
|
||||
pIter->iOff = iOff;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fts5DlidxIterLast(Fts5DlidxIter *pIter){
|
||||
while( 0==fts5DlidxIterNext(pIter, 0) );
|
||||
assert( pIter->iOff==pIter->pData->n && pIter->bEof==1 );
|
||||
pIter->bEof = 0;
|
||||
}
|
||||
|
||||
static int fts5DlidxIterEof(Fts5Index *p, Fts5DlidxIter *pIter){
|
||||
return (p->rc!=SQLITE_OK || pIter->bEof);
|
||||
return pIter->bEof;
|
||||
}
|
||||
|
||||
static void fts5DlidxIterInit(
|
||||
@ -1213,10 +1253,9 @@ static void fts5DlidxIterInit(
|
||||
}
|
||||
|
||||
pIter->pData = pDlidx;
|
||||
|
||||
pIter->iLeafPgno = iLeafPgno;
|
||||
if( bRev==0 ){
|
||||
fts5DlidxIterNext(pIter, 0);
|
||||
fts5DlidxIterFirst(pIter);
|
||||
}else{
|
||||
fts5DlidxIterLast(pIter);
|
||||
}
|
||||
@ -1438,44 +1477,6 @@ static void fts5SegIterNext(
|
||||
pIter->iRowid += iDelta;
|
||||
}else{
|
||||
fts5SegIterReverseNewPage(p, pIter);
|
||||
#if 0
|
||||
fts5DataRelease(pIter->pLeaf);
|
||||
pIter->pLeaf = 0;
|
||||
while( p->rc==SQLITE_OK && pIter->iLeafPgno>pIter->iTermLeafPgno ){
|
||||
Fts5Data *pNew;
|
||||
pIter->iLeafPgno--;
|
||||
pNew = fts5DataRead(p, FTS5_SEGMENT_ROWID(
|
||||
pIter->iIdx, pIter->pSeg->iSegid, 0, pIter->iLeafPgno
|
||||
));
|
||||
if( pNew ){
|
||||
if( pIter->iLeafPgno==pIter->iTermLeafPgno ){
|
||||
if( pIter->iTermLeafOffset<pNew->n ){
|
||||
pIter->pLeaf = pNew;
|
||||
pIter->iLeafOffset = pIter->iTermLeafOffset;
|
||||
}
|
||||
}else{
|
||||
int iRowidOff, dummy;
|
||||
fts5LeafHeader(pNew, &iRowidOff, &dummy);
|
||||
if( iRowidOff ){
|
||||
pIter->pLeaf = pNew;
|
||||
pIter->iLeafOffset = iRowidOff;
|
||||
}
|
||||
}
|
||||
|
||||
if( pIter->pLeaf ){
|
||||
u8 *a = &pIter->pLeaf->p[pIter->iLeafOffset];
|
||||
pIter->iLeafOffset += getVarint(a, (u64*)&pIter->iRowid);
|
||||
break;
|
||||
}else{
|
||||
fts5DataRelease(pNew);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( pIter->pLeaf ){
|
||||
fts5SegIterReverseInitPage(p, pIter);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}else{
|
||||
Fts5Data *pLeaf = pIter->pLeaf;
|
||||
@ -1555,43 +1556,49 @@ static void fts5SegIterReverse(Fts5Index *p, int iIdx, Fts5SegIter *pIter){
|
||||
/* Move to the page that contains the last rowid in this doclist. */
|
||||
pLeaf = pIter->pLeaf;
|
||||
|
||||
while( iOff<pLeaf->n ){
|
||||
int nPos;
|
||||
i64 iDelta;
|
||||
if( pIter->pDlidx ){
|
||||
int iSegid = pIter->pSeg->iSegid;
|
||||
pgnoLast = pIter->pDlidx->iLeafPgno;
|
||||
pLast = fts5DataRead(p, FTS5_SEGMENT_ROWID(iIdx, iSegid, 0, pgnoLast));
|
||||
}else{
|
||||
while( iOff<pLeaf->n ){
|
||||
int nPos;
|
||||
i64 iDelta;
|
||||
|
||||
/* Position list size in bytes */
|
||||
iOff += getVarint32(&pLeaf->p[iOff], nPos);
|
||||
iOff += nPos;
|
||||
if( iOff>=pLeaf->n ) break;
|
||||
/* Position list size in bytes */
|
||||
iOff += getVarint32(&pLeaf->p[iOff], nPos);
|
||||
iOff += nPos;
|
||||
if( iOff>=pLeaf->n ) break;
|
||||
|
||||
/* Rowid delta. Or, if 0x00, the end of doclist marker. */
|
||||
nPos = getVarint(&pLeaf->p[iOff], (u64*)&iDelta);
|
||||
if( iDelta==0 ) break;
|
||||
iOff += nPos;
|
||||
}
|
||||
/* Rowid delta. Or, if 0x00, the end of doclist marker. */
|
||||
nPos = getVarint(&pLeaf->p[iOff], (u64*)&iDelta);
|
||||
if( iDelta==0 ) break;
|
||||
iOff += nPos;
|
||||
}
|
||||
|
||||
if( iOff>=pLeaf->n ){
|
||||
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);
|
||||
if( iOff>=pLeaf->n ){
|
||||
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++){
|
||||
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);
|
||||
/* 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++){
|
||||
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;
|
||||
}
|
||||
fts5DataRelease(pNew);
|
||||
}
|
||||
if( iTerm ){
|
||||
iAbs = iLast;
|
||||
}
|
||||
fts5DataRelease(pNew);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1615,7 +1622,6 @@ static void fts5SegIterReverse(Fts5Index *p, int iIdx, Fts5SegIter *pIter){
|
||||
}
|
||||
|
||||
fts5SegIterReverseInitPage(p, pIter);
|
||||
pIter->flags |= FTS5_SEGITER_REVERSE;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1733,6 +1739,9 @@ static void fts5SegIterSeekInit(
|
||||
if( bGe==0 ){
|
||||
pIter->flags |= FTS5_SEGITER_ONETERM;
|
||||
if( pIter->pLeaf ){
|
||||
if( flags & FTS5INDEX_QUERY_ASC ){
|
||||
pIter->flags |= FTS5_SEGITER_REVERSE;
|
||||
}
|
||||
if( bDlidx ){
|
||||
fts5SegIterLoadDlidx(p, iIdx, pIter);
|
||||
}
|
||||
@ -1879,37 +1888,44 @@ static void fts5SegIterNextFrom(
|
||||
int bRev = (pIter->flags & FTS5_SEGITER_REVERSE);
|
||||
Fts5DlidxIter *pDlidx = pIter->pDlidx;
|
||||
int iLeafPgno = pIter->iLeafPgno;
|
||||
int bMove = 1;
|
||||
|
||||
assert( pIter->flags & FTS5_SEGITER_ONETERM );
|
||||
assert( pIter->pDlidx );
|
||||
assert( pIter->pLeaf );
|
||||
|
||||
|
||||
if( bRev==0 ){
|
||||
while( fts5DlidxIterEof(p, pDlidx)==0 && iMatch<pDlidx->iRowid ){
|
||||
if( pDlidx->bZero==0 ) iLeafPgno = pDlidx->iLeafPgno;
|
||||
fts5DlidxIterNext(pDlidx, 0);
|
||||
iLeafPgno = pDlidx->iLeafPgno;
|
||||
fts5DlidxIterNext(pDlidx);
|
||||
}
|
||||
assert( iLeafPgno>=pIter->iLeafPgno || p->rc );
|
||||
if( iLeafPgno>pIter->iLeafPgno ){
|
||||
fts5SegIterGotoPage(p, pIter, iLeafPgno);
|
||||
bMove = 0;
|
||||
}
|
||||
}else if( 0 ){
|
||||
}else{
|
||||
assert( iMatch>pIter->iRowid );
|
||||
while( fts5DlidxIterEof(p, pDlidx)==0 && iMatch>pDlidx->iRowid ){
|
||||
fts5DlidxIterNext(pDlidx, 0);
|
||||
if( pDlidx->bZero==0 ) iLeafPgno = pDlidx->iLeafPgno;
|
||||
fts5DlidxIterPrev(pDlidx);
|
||||
}
|
||||
assert( iLeafPgno<=pIter->iLeafPgno || p->rc );
|
||||
iLeafPgno = pDlidx->iLeafPgno;
|
||||
|
||||
assert( fts5DlidxIterEof(p, pDlidx) || iLeafPgno<=pIter->iLeafPgno );
|
||||
|
||||
if( iLeafPgno<pIter->iLeafPgno ){
|
||||
fts5SegIterGotoPage(p, pIter, iLeafPgno);
|
||||
pIter->iLeafPgno = iLeafPgno+1;
|
||||
fts5SegIterReverseNewPage(p, pIter);
|
||||
bMove = 0;
|
||||
}
|
||||
}
|
||||
|
||||
while( 1 ){
|
||||
fts5SegIterNext(p, pIter);
|
||||
if( bMove ) fts5SegIterNext(p, pIter);
|
||||
if( pIter->pLeaf==0 ) break;
|
||||
if( bRev==0 && pIter->iRowid<=iMatch ) break;
|
||||
if( bRev!=0 && pIter->iRowid>=iMatch ) break;
|
||||
bMove = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3377,7 +3393,50 @@ static void fts5BtreeIterFree(Fts5BtreeIter *pIter){
|
||||
fts5BufferFree(&pIter->term);
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is purely an internal test. It does not contribute to
|
||||
** FTS functionality, or even the integrity-check, in any way.
|
||||
**
|
||||
** Instead, it tests that the same set of pgno/rowid combinations are
|
||||
** visited regardless of whether the doclist-index identified by parameters
|
||||
** iIdx/iSegid/iLeaf is iterated in forwards or reverse order.
|
||||
*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
static void fts5DlidxIterTestReverse(
|
||||
Fts5Index *p,
|
||||
int iIdx, /* Index to load doclist-index from */
|
||||
int iSegid, /* Segment id to load from */
|
||||
int iLeaf /* Load doclist-index for this leaf */
|
||||
){
|
||||
Fts5DlidxIter *pDlidx = 0;
|
||||
i64 cksum1 = 13;
|
||||
i64 cksum2 = 13;
|
||||
|
||||
for(fts5DlidxIterInit(p, 0, iIdx, iSegid, iLeaf, &pDlidx);
|
||||
fts5DlidxIterEof(p, pDlidx)==0;
|
||||
fts5DlidxIterNext(pDlidx)
|
||||
){
|
||||
cksum1 = (cksum1 ^ ( (i64)(pDlidx->iLeafPgno) << 32 ));
|
||||
cksum1 = (cksum1 ^ pDlidx->iRowid);
|
||||
}
|
||||
fts5DlidxIterFree(pDlidx);
|
||||
pDlidx = 0;
|
||||
|
||||
for(fts5DlidxIterInit(p, 1, iIdx, iSegid, iLeaf, &pDlidx);
|
||||
fts5DlidxIterEof(p, pDlidx)==0;
|
||||
fts5DlidxIterPrev(pDlidx)
|
||||
){
|
||||
cksum2 = (cksum2 ^ ( (i64)(pDlidx->iLeafPgno) << 32 ));
|
||||
cksum2 = (cksum2 ^ pDlidx->iRowid);
|
||||
}
|
||||
fts5DlidxIterFree(pDlidx);
|
||||
pDlidx = 0;
|
||||
|
||||
if( p->rc==SQLITE_OK && cksum1!=cksum2 ) p->rc = FTS5_CORRUPT;
|
||||
}
|
||||
#else
|
||||
# define fts5DlidxIterTestReverse(w,x,y,z)
|
||||
#endif
|
||||
|
||||
static void fts5IndexIntegrityCheckSegment(
|
||||
Fts5Index *p, /* FTS5 backend object */
|
||||
@ -3421,7 +3480,6 @@ static void fts5IndexIntegrityCheckSegment(
|
||||
fts5DataRelease(pLeaf);
|
||||
if( p->rc ) break;
|
||||
|
||||
|
||||
/* Now check that the iter.nEmpty leaves following the current leaf
|
||||
** (a) exist and (b) contain no terms. */
|
||||
for(i=1; p->rc==SQLITE_OK && i<=iter.nEmpty; i++){
|
||||
@ -3435,35 +3493,52 @@ static void fts5IndexIntegrityCheckSegment(
|
||||
/* If there is a doclist-index, check that it looks right. */
|
||||
if( iter.bDlidx ){
|
||||
Fts5DlidxIter *pDlidx = 0; /* For iterating through doclist index */
|
||||
int nEntry = 0;
|
||||
int iPrevLeaf = iter.iLeaf;
|
||||
int iSegid = pSeg->iSegid;
|
||||
int bRev = 0;
|
||||
int iPg;
|
||||
i64 iKey;
|
||||
|
||||
for(fts5DlidxIterInit(p, bRev, iIdx, iSegid, iter.iLeaf, &pDlidx);
|
||||
for(fts5DlidxIterInit(p, 0, iIdx, iSegid, iter.iLeaf, &pDlidx);
|
||||
fts5DlidxIterEof(p, pDlidx)==0;
|
||||
fts5DlidxIterNext(pDlidx, bRev)
|
||||
fts5DlidxIterNext(pDlidx)
|
||||
){
|
||||
i64 iKey = FTS5_SEGMENT_ROWID(iIdx, iSegid, 0, pDlidx->iLeafPgno);
|
||||
|
||||
/* Check any rowid-less pages that occur before the current leaf. */
|
||||
for(iPg=iPrevLeaf+1; iPg<pDlidx->iLeafPgno; iPg++){
|
||||
iKey = FTS5_SEGMENT_ROWID(iIdx, iSegid, 0, iPg);
|
||||
pLeaf = fts5DataRead(p, iKey);
|
||||
if( pLeaf ){
|
||||
if( fts5GetU16(&pLeaf->p[0])!=0 ) p->rc = FTS5_CORRUPT;
|
||||
fts5DataRelease(pLeaf);
|
||||
}
|
||||
}
|
||||
iPrevLeaf = pDlidx->iLeafPgno;
|
||||
|
||||
/* Check that the leaf page indicated by the iterator really does
|
||||
** contain the rowid suggested by the same. */
|
||||
iKey = FTS5_SEGMENT_ROWID(iIdx, iSegid, 0, pDlidx->iLeafPgno);
|
||||
pLeaf = fts5DataRead(p, iKey);
|
||||
if( pLeaf ){
|
||||
i64 iRowid;
|
||||
int iRowidOff = fts5GetU16(&pLeaf->p[0]);
|
||||
if( pDlidx->bZero ){
|
||||
if( iRowidOff!=0 ) p->rc = FTS5_CORRUPT;
|
||||
}else{
|
||||
i64 iRowid;
|
||||
getVarint(&pLeaf->p[iRowidOff], (u64*)&iRowid);
|
||||
if( iRowid!=pDlidx->iRowid ) p->rc = FTS5_CORRUPT;
|
||||
}
|
||||
getVarint(&pLeaf->p[iRowidOff], (u64*)&iRowid);
|
||||
if( iRowid!=pDlidx->iRowid ) p->rc = FTS5_CORRUPT;
|
||||
fts5DataRelease(pLeaf);
|
||||
}
|
||||
nEntry++;
|
||||
|
||||
}
|
||||
|
||||
/* Check that the doclist-index was the right length */
|
||||
if( p->rc==SQLITE_OK && nEntry!=iter.nEmpty && nEntry!=iter.nEmpty+1 ){
|
||||
p->rc = FTS5_CORRUPT;
|
||||
for(iPg=iPrevLeaf+1; iPg<=(iter.iLeaf + iter.nEmpty); iPg++){
|
||||
iKey = FTS5_SEGMENT_ROWID(iIdx, iSegid, 0, iPg);
|
||||
pLeaf = fts5DataRead(p, iKey);
|
||||
if( pLeaf ){
|
||||
if( fts5GetU16(&pLeaf->p[0])!=0 ) p->rc = FTS5_CORRUPT;
|
||||
fts5DataRelease(pLeaf);
|
||||
}
|
||||
}
|
||||
|
||||
fts5DlidxIterFree(pDlidx);
|
||||
fts5DlidxIterTestReverse(p, iIdx, iSegid, iter.iLeaf);
|
||||
}
|
||||
}
|
||||
|
||||
|
18
manifest
18
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\sfts5_index.c\sto\suse\sdoclist-indexes\swhen\spossible.\sOnly\ssome\scases\swork\sso\sfar.
|
||||
D 2014-08-04T20:07:40.532
|
||||
C Use\sdoclist-indexes\swith\s"ORDER\sBY\srowid\sASC"\sfts5\squeries\sas\swell.
|
||||
D 2014-08-05T19:00:22.438
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in b03432313a3aad96c706f8164fb9f5307eaf19f5
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -110,7 +110,7 @@ F ext/fts5/fts5_aux.c 366057c7186bc3615deb5ecc0ff61de50b6d2dbc
|
||||
F ext/fts5/fts5_buffer.c 248c61ac9fec001602efc72a45704f3b8d367c00
|
||||
F ext/fts5/fts5_config.c f4ebf143e141b8c77355e3b15aba81b7be51d710
|
||||
F ext/fts5/fts5_expr.c 9402474456732ddb5019f83a77907852f108a96a
|
||||
F ext/fts5/fts5_index.c 3578823a9a43fcc77ce46c7f6efddfd155544053
|
||||
F ext/fts5/fts5_index.c 40d9086948d6f1420a078bd9fb0b5372e54ec791
|
||||
F ext/fts5/fts5_storage.c 2866e7e1de9dc851756c3a9c76b6e1d75e0facb7
|
||||
F ext/fts5/fts5parse.y 777da8e5819f75c217982c79c29d014c293acac9
|
||||
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
|
||||
@ -595,14 +595,14 @@ F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7
|
||||
F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
|
||||
F test/fts4noti.test 524807f0c36d49deea7920cdd4cd687408b58849
|
||||
F test/fts4unicode.test 01ec3fe2a7c3cfff3b4c0581b83caa11b33efa36
|
||||
F test/fts5aa.test f54245091fee924030722234070fcba95a493549
|
||||
F test/fts5aa.test 2d136b61c4523ec018699e59b35c005313569b9e
|
||||
F test/fts5ab.test dc04ed48cf93ca957d174406e6c192f2ff4f3397
|
||||
F test/fts5ac.test 9be418d037763f4cc5d86f4239db41fc86bb4f85
|
||||
F test/fts5ac.test 399533fe52b7383053368ab8ba01ae182391e5d7
|
||||
F test/fts5ad.test 2ed38bbc865678cb2905247120d02ebba7f20e07
|
||||
F test/fts5ae.test cb37b3135a00d3afd5492ec534ecf654be5ff69e
|
||||
F test/fts5af.test 9ebe23aa3875896076952c7bc6e8308813a63c74
|
||||
F test/fts5ag.test 0747bf3bade16d5165810cf891f875933b28b420
|
||||
F test/fts5ah.test ca1f12b5738992c2edbdeb6c16133d41cfb9c031
|
||||
F test/fts5ah.test 009b993a9b7ebc43f84c10e53bd778b1dc8ffbe7
|
||||
F test/fts5ea.test ff43b40f8879ba50b82def70f2ab67c195d1a1d4
|
||||
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
||||
F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef
|
||||
@ -1199,7 +1199,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 b8864da95db2c0e611116304d607e35a86c9247d
|
||||
R 2807aba63fb0a8821d708dc4cbc7f577
|
||||
P 90b82d3ef613b2915e0e280dc1d2e5a2b617d59c
|
||||
R 0266e2e08ce753d75d582fc91e12512e
|
||||
U dan
|
||||
Z 6114a7973c3151dffa74bd597b78489f
|
||||
Z 1a32a19af984c36e1b27a239a8950f8a
|
||||
|
@ -1 +1 @@
|
||||
90b82d3ef613b2915e0e280dc1d2e5a2b617d59c
|
||||
d028ba6589f3122b635474c2683c0f93d5bc6c7c
|
@ -148,6 +148,7 @@ do_execsql_test 6.2 {
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
expr srand(0)
|
||||
do_execsql_test 7.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x,y,z);
|
||||
INSERT INTO t1(t1) VALUES('pgsz=32');
|
||||
@ -173,7 +174,7 @@ proc dump_structure {} {
|
||||
|
||||
for {set i 1} {$i <= 10} {incr i} {
|
||||
do_test 7.$i {
|
||||
for {set j 0} {$j < 100} {incr j} {
|
||||
for {set j 0} {$j < 10} {incr j} {
|
||||
set x [doc]
|
||||
set y [doc]
|
||||
set z [doc]
|
||||
|
@ -364,6 +364,10 @@ foreach {tn expr tclexpr} {
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
do_execsql_test 6.integrity {
|
||||
INSERT INTO xx(xx) VALUES('integrity-check');
|
||||
}
|
||||
#db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM xx_data} {puts $r}
|
||||
foreach {bAsc sql} {
|
||||
0 {SELECT rowid FROM xx WHERE xx MATCH $expr}
|
||||
1 {SELECT rowid FROM xx WHERE xx MATCH $expr ORDER BY rowid ASC}
|
||||
|
@ -53,6 +53,12 @@ proc reads {} {
|
||||
db one {SELECT t1 FROM t1 WHERE t1 MATCH '*reads'}
|
||||
}
|
||||
|
||||
proc execsql_reads {sql} {
|
||||
set nRead [reads]
|
||||
execsql $sql
|
||||
expr [reads] - $nRead
|
||||
}
|
||||
|
||||
do_test 1.4 {
|
||||
set nRead [reads]
|
||||
execsql { SELECT rowid FROM t1 WHERE t1 MATCH 'x' }
|
||||
@ -60,6 +66,14 @@ do_test 1.4 {
|
||||
expr $nReadX>1000
|
||||
} {1}
|
||||
|
||||
do_test 1.5 {
|
||||
set fwd [execsql_reads {SELECT rowid FROM t1 WHERE t1 MATCH 'x' }]
|
||||
set bwd [execsql_reads {
|
||||
SELECT rowid FROM t1 WHERE t1 MATCH 'x' ORDER BY 1 ASC
|
||||
}]
|
||||
expr {$bwd < $fwd + 10}
|
||||
} {1}
|
||||
|
||||
foreach {tn q res} "
|
||||
1 { SELECT rowid FROM t1 WHERE t1 MATCH 'w + x' } [list $W]
|
||||
2 { SELECT rowid FROM t1 WHERE t1 MATCH 'x + w' } [list $W]
|
||||
@ -67,22 +81,18 @@ foreach {tn q res} "
|
||||
4 { SELECT rowid FROM t1 WHERE t1 MATCH 'y AND x' } [list $Y]
|
||||
" {
|
||||
|
||||
do_test 1.5.$tn.1 {
|
||||
set nRead [reads]
|
||||
execsql $q
|
||||
set n [expr [reads] - $nRead]
|
||||
do_test 1.6.$tn.1 {
|
||||
set n [execsql_reads $q]
|
||||
expr {$n < ($nReadX / 10)}
|
||||
} {1}
|
||||
|
||||
do_test 1.5.$tn.2 {
|
||||
set nRead [reads]
|
||||
execsql "$q ORDER BY rowid ASC"
|
||||
set n [expr [reads] - $nRead]
|
||||
do_test 1.6.$tn.2 {
|
||||
set n [execsql_reads "$q ORDER BY rowid ASC"]
|
||||
expr {$n < ($nReadX / 10)}
|
||||
} {1}
|
||||
|
||||
do_execsql_test 1.5.$tn.3 $q [lsort -int -decr $res]
|
||||
do_execsql_test 1.5.$tn.4 "$q ORDER BY rowid ASC" [lsort -int -incr $res]
|
||||
do_execsql_test 1.6.$tn.3 $q [lsort -int -decr $res]
|
||||
do_execsql_test 1.6.$tn.4 "$q ORDER BY rowid ASC" [lsort -int -incr $res]
|
||||
}
|
||||
|
||||
#db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM t1_data} {puts $r}
|
||||
|
Reference in New Issue
Block a user