From: dan Date: Sat, 24 Jan 2015 19:57:03 +0000 (+0000) Subject: Have fts5 store rowids in ascending order. Query speed is virtually the same regardle... X-Git-Tag: version-3.8.11~114^2~93 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8ac3025419ba812747fdc685723946778ee54c54;p=thirdparty%2Fsqlite.git Have fts5 store rowids in ascending order. Query speed is virtually the same regardless of rowid order, and ascending order makes some insert optimizations easier. FossilOrigin-Name: 5206ca6005bfa9dfc7346d4b89430c9748d32c10 --- diff --git a/ext/fts5/fts5.c b/ext/fts5/fts5.c index c61598e477..d748a8b40f 100644 --- a/ext/fts5/fts5.c +++ b/ext/fts5/fts5.c @@ -505,7 +505,7 @@ static int fts5OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ static int fts5StmtType(int idxNum){ if( FTS5_PLAN(idxNum)==FTS5_PLAN_SCAN ){ - return (idxNum&FTS5_ORDER_ASC) ? FTS5_STMT_SCAN_ASC : FTS5_STMT_SCAN_DESC; + return (idxNum&FTS5_ORDER_DESC) ? FTS5_STMT_SCAN_DESC : FTS5_STMT_SCAN_ASC; } return FTS5_STMT_LOOKUP; } @@ -652,7 +652,7 @@ static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){ return rc; } -static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bAsc){ +static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){ Fts5Config *pConfig = pTab->pConfig; Fts5Sorter *pSorter; int nPhrase; @@ -680,7 +680,7 @@ static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bAsc){ pConfig->zDb, pConfig->zName, zRank, pConfig->zName, (zRankArgs ? ", " : ""), (zRankArgs ? zRankArgs : ""), - bAsc ? "ASC" : "DESC" + bDesc ? "DESC" : "ASC" ); if( zSql==0 ){ rc = SQLITE_NOMEM; @@ -706,9 +706,9 @@ static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bAsc){ return rc; } -static int fts5CursorFirst(Fts5Table *pTab, Fts5Cursor *pCsr, int bAsc){ +static int fts5CursorFirst(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){ int rc; - rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->pIndex, bAsc); + rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->pIndex, bDesc); if( sqlite3Fts5ExprEof(pCsr->pExpr) ){ CsrFlagSet(pCsr, FTS5CSR_EOF); } @@ -873,7 +873,7 @@ static int fts5FilterMethod( ){ Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab); Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; - int bAsc = ((idxNum & FTS5_ORDER_ASC) ? 1 : 0); + int bDesc = ((idxNum & FTS5_ORDER_DESC) ? 1 : 0); int rc = SQLITE_OK; assert( nVal<=2 ); @@ -894,7 +894,7 @@ static int fts5FilterMethod( assert( FTS5_PLAN(idxNum)==FTS5_PLAN_SCAN ); pCsr->idxNum = FTS5_PLAN_SOURCE; pCsr->pExpr = pTab->pSortCsr->pExpr; - rc = fts5CursorFirst(pTab, pCsr, bAsc); + rc = fts5CursorFirst(pTab, pCsr, bDesc); }else{ int ePlan = FTS5_PLAN(idxNum); pCsr->idxNum = idxNum; @@ -913,9 +913,9 @@ static int fts5FilterMethod( rc = sqlite3Fts5ExprNew(pTab->pConfig, zExpr, &pCsr->pExpr, pzErr); if( rc==SQLITE_OK ){ if( ePlan==FTS5_PLAN_MATCH ){ - rc = fts5CursorFirst(pTab, pCsr, bAsc); + rc = fts5CursorFirst(pTab, pCsr, bDesc); }else{ - rc = fts5CursorFirstSorted(pTab, pCsr, bAsc); + rc = fts5CursorFirstSorted(pTab, pCsr, bDesc); } } } diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index 728b6461a1..50003632d1 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -229,7 +229,7 @@ typedef struct Fts5IndexIter Fts5IndexIter; ** Values used as part of the flags argument passed to IndexQuery(). */ #define FTS5INDEX_QUERY_PREFIX 0x0001 /* Prefix query */ -#define FTS5INDEX_QUERY_ASC 0x0002 /* Docs in ascending rowid order */ +#define FTS5INDEX_QUERY_DESC 0x0002 /* Docs in descending rowid order */ /* ** Create/destroy an Fts5Index object. @@ -365,6 +365,13 @@ int sqlite3Fts5GetVarint32(const unsigned char *p, u32 *v); */ typedef struct Fts5Hash Fts5Hash; +typedef struct Fts5Data Fts5Data; +struct Fts5Data { + u8 *p; /* Pointer to buffer containing record */ + int n; /* Size of record in bytes */ + int nRef; /* Ref count */ +}; + /* ** Create a hash table, free a hash table. */ @@ -395,6 +402,11 @@ int sqlite3Fts5HashIterate( int (*xTermDone)(void*) ); +int sqlite3Fts5HashQuery( + Fts5Hash*, /* Hash table to query */ + const char *pTerm, int nTerm, /* Query term */ + Fts5Data **ppData /* OUT: Query result */ +); /* @@ -470,7 +482,7 @@ int sqlite3Fts5ExprNew( ); /* -** for(rc = sqlite3Fts5ExprFirst(pExpr, pIdx, bAsc); +** for(rc = sqlite3Fts5ExprFirst(pExpr, pIdx, bDesc); ** rc==SQLITE_OK && 0==sqlite3Fts5ExprEof(pExpr); ** rc = sqlite3Fts5ExprNext(pExpr) ** ){ @@ -478,7 +490,7 @@ int sqlite3Fts5ExprNew( ** i64 iRowid = sqlite3Fts5ExprRowid(pExpr); ** } */ -int sqlite3Fts5ExprFirst(Fts5Expr*, Fts5Index *pIdx, int bAsc); +int sqlite3Fts5ExprFirst(Fts5Expr*, Fts5Index *pIdx, int bDesc); int sqlite3Fts5ExprNext(Fts5Expr*); int sqlite3Fts5ExprEof(Fts5Expr*); i64 sqlite3Fts5ExprRowid(Fts5Expr*); diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c index 71f8b48069..bbf8c68acb 100644 --- a/ext/fts5/fts5_expr.c +++ b/ext/fts5/fts5_expr.c @@ -32,7 +32,7 @@ void sqlite3Fts5Parser(void*, int, Fts5Token, Fts5Parse*); struct Fts5Expr { Fts5Index *pIndex; Fts5ExprNode *pRoot; - int bAsc; + int bDesc; /* Iterate in descending docid order */ int nPhrase; /* Number of phrases in expression */ Fts5ExprPhrase **apExprPhrase; /* Pointers to phrase objects */ }; @@ -600,9 +600,9 @@ static int fts5ExprNearAdvanceAll( } /* -** Advance iterator pIter until it points to a value equal to or smaller -** than the initial value of *piMin. If this means the iterator points -** to a value smaller than *piMin, update *piMin to the new smallest value. +** Advance iterator pIter until it points to a value equal to or laster +** than the initial value of *piLast. If this means the iterator points +** to a value laster than *piLast, update *piLast to the new lastest value. ** ** If the iterator reaches EOF, set *pbEof to true before returning. If ** an error occurs, set *pRc to an error code. If either *pbEof or *pRc @@ -610,7 +610,7 @@ static int fts5ExprNearAdvanceAll( */ static int fts5ExprAdvanceto( Fts5IndexIter *pIter, /* Iterator to advance */ - int bAsc, /* True if iterator is "rowid ASC" */ + int bDesc, /* True if iterator is "rowid DESC" */ i64 *piLast, /* IN/OUT: Lastest rowid seen so far */ int *pRc, /* OUT: Error code */ int *pbEof /* OUT: Set to true if EOF */ @@ -619,14 +619,14 @@ static int fts5ExprAdvanceto( i64 iRowid; iRowid = sqlite3Fts5IterRowid(pIter); - if( (bAsc==0 && iRowid>iLast) || (bAsc && iRowidiRowid) || (bDesc && iLast=iLast) ); + assert( (bDesc==0 && iRowid>=iLast) || (bDesc==1 && iRowid<=iLast) ); } *piLast = iRowid; @@ -656,12 +656,13 @@ static int fts5ExprNearNextRowidMatch( i64 iLast; /* Lastest rowid any iterator points to */ int bMatch; /* True if all terms are at the same rowid */ - /* Set iLast, the lastest rowid any iterator points to. If the iterator - ** skips through rowids in the default descending order, this means the - ** minimum rowid. Or, if the iterator is "ORDER BY rowid ASC", then it - ** means the maximum rowid. */ + /* Initialize iLast, the "lastest" rowid any iterator points to. If the + ** iterator skips through rowids in the default ascending order, this means + ** the maximum rowid. Or, if the iterator is "ORDER BY rowid DESC", then it + ** means the minimum rowid. */ iLast = sqlite3Fts5IterRowid(pNear->apPhrase[0]->aTerm[0].pIter); - if( bFromValid && (iFrom>iLast)==(pExpr->bAsc!=0) ){ + if( bFromValid && (iFrom>iLast)==(pExpr->bDesc==0) ){ + assert( pExpr->bDesc || iFrom>=iLast ); iLast = iFrom; } @@ -673,7 +674,7 @@ static int fts5ExprNearNextRowidMatch( Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter; i64 iRowid = sqlite3Fts5IterRowid(pIter); if( iRowid!=iLast ) bMatch = 0; - if( fts5ExprAdvanceto(pIter, pExpr->bAsc, &iLast, &rc, &pNode->bEof) ){ + if( fts5ExprAdvanceto(pIter, pExpr->bDesc, &iLast, &rc, &pNode->bEof) ){ return rc; } } @@ -774,7 +775,7 @@ static int fts5ExprNearInitAll( rc = sqlite3Fts5IndexQuery( pExpr->pIndex, pTerm->zTerm, strlen(pTerm->zTerm), (pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) | - (pExpr->bAsc ? FTS5INDEX_QUERY_ASC : 0), + (pExpr->bDesc ? FTS5INDEX_QUERY_DESC : 0), &pTerm->pIter ); assert( rc==SQLITE_OK || pTerm->pIter==0 ); @@ -810,7 +811,7 @@ static int fts5NodeCompare( ){ if( p2->bEof ) return -1; if( p1->bEof ) return +1; - if( pExpr->bAsc ){ + if( pExpr->bDesc==0 ){ if( p1->iRowidiRowid ) return -1; return (p1->iRowid > p2->iRowid); }else{ @@ -911,18 +912,17 @@ static int fts5ExprNodeNextMatch( Fts5ExprNode *p1 = pNode->pLeft; Fts5ExprNode *p2 = pNode->pRight; - while( p1->bEof==0 && p2->bEof==0 && p2->iRowid!=p1->iRowid ){ Fts5ExprNode *pAdv; - assert( pExpr->bAsc==0 || pExpr->bAsc==1 ); - if( pExpr->bAsc==(p1->iRowid < p2->iRowid) ){ + assert( pExpr->bDesc==0 || pExpr->bDesc==1 ); + if( pExpr->bDesc==(p1->iRowid > p2->iRowid) ){ pAdv = p1; - if( bFromValid==0 || pExpr->bAsc==(p2->iRowid > iFrom) ){ + if( bFromValid==0 || pExpr->bDesc==(p2->iRowid < iFrom) ){ iFrom = p2->iRowid; } }else{ pAdv = p2; - if( bFromValid==0 || pExpr->bAsc==(p1->iRowid > iFrom) ){ + if( bFromValid==0 || pExpr->bDesc==(p1->iRowid < iFrom) ){ iFrom = p1->iRowid; } } @@ -1003,18 +1003,18 @@ static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){ /* ** Begin iterating through the set of documents in index pIdx matched by -** the MATCH expression passed as the first argument. If the "bAsc" parameter -** is passed a non-zero value, iteration is in ascending rowid order. Or, -** if it is zero, in descending order. +** the MATCH expression passed as the first argument. If the "bDesc" parameter +** is passed a non-zero value, iteration is in descending rowid order. Or, +** if it is zero, in ascending order. ** ** Return SQLITE_OK if successful, or an SQLite error code otherwise. It ** is not considered an error if the query does not match any documents. */ -int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, int bAsc){ +int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, int bDesc){ int rc = SQLITE_OK; if( p->pRoot ){ p->pIndex = pIdx; - p->bAsc = bAsc; + p->bDesc = bDesc; rc = fts5ExprNodeFirst(p, p->pRoot); } return rc; diff --git a/ext/fts5/fts5_hash.c b/ext/fts5/fts5_hash.c index 61eed74be4..41b2eb774a 100644 --- a/ext/fts5/fts5_hash.c +++ b/ext/fts5/fts5_hash.c @@ -55,7 +55,7 @@ struct Fts5HashEntry { Fts5HashEntry *pNext; /* Next hash entry with same hash-key */ int nAlloc; /* Total size of allocation */ - int iRowidOff; /* Offset of last rowid written */ + int iSzPoslist; /* Offset of space for 4-byte poslist size */ int nData; /* Total bytes of data (incl. structure) */ int iCol; /* Column of last value written */ @@ -64,6 +64,16 @@ struct Fts5HashEntry { char zKey[0]; /* Nul-terminated entry key */ }; +/* +** Format value iVal as a 4-byte varint and write it to buffer a[]. 4 bytes +** are used even if the value could fit in a smaller amount of space. +*/ +static void fts5Put4ByteVarint(u8 *a, int iVal){ + a[0] = (0x80 | (u8)(iVal >> 21)); + a[1] = (0x80 | (u8)(iVal >> 14)); + a[2] = (0x80 | (u8)(iVal >> 7)); + a[3] = (0x7F & (u8)(iVal)); +} /* ** Allocate a new hash table. @@ -161,25 +171,6 @@ static int fts5HashResize(Fts5Hash *pHash){ return SQLITE_OK; } -/* -** Store the 32-bit integer passed as the second argument in buffer p. -*/ -static int fts5PutNativeInt(u8 *p, int i){ - assert( sizeof(i)==4 ); - memcpy(p, &i, sizeof(i)); - return sizeof(i); -} - -/* -** Read and return the 32-bit integer stored in buffer p. -*/ -static int fts5GetNativeU32(u8 *p){ - int i; - assert( sizeof(i)==4 ); - memcpy(&i, p, sizeof(i)); - return i; -} - int sqlite3Fts5HashWrite( Fts5Hash *pHash, i64 iRowid, /* Rowid for this entry */ @@ -192,7 +183,7 @@ int sqlite3Fts5HashWrite( u8 *pPtr; int nIncr = 0; /* Amount to increment (*pHash->pnByte) by */ - /* Attempt to locate an existing hash object */ + /* Attempt to locate an existing hash entry */ for(p=pHash->aSlot[iHash]; p; p=p->pNext){ if( memcmp(p->zKey, pToken, nToken)==0 && p->zKey[nToken]==0 ) break; } @@ -214,26 +205,27 @@ int sqlite3Fts5HashWrite( p->nAlloc = nByte; memcpy(p->zKey, pToken, nToken); p->zKey[nToken] = '\0'; - p->iRowidOff = p->nData = nToken + 1 + sizeof(Fts5HashEntry); + p->nData = nToken + 1 + sizeof(Fts5HashEntry); p->nData += sqlite3PutVarint(&((u8*)p)[p->nData], iRowid); + p->iSzPoslist = p->nData; + p->nData += 4; p->iRowid = iRowid; p->pNext = pHash->aSlot[iHash]; pHash->aSlot[iHash] = p; pHash->nEntry++; - nIncr += p->nData; } /* Check there is enough space to append a new entry. Worst case scenario ** is: ** - ** + 4 bytes for the previous entry size field, ** + 9 bytes for a new rowid, + ** + 4 bytes reserved for the "poslist size" varint. ** + 1 byte for a "new column" byte, ** + 3 bytes for a new column number (16-bit max) as a varint, ** + 5 bytes for the new position offset (32-bit max). */ - if( (p->nAlloc - p->nData) < (4 + 9 + 1 + 3 + 5) ){ + if( (p->nAlloc - p->nData) < (9 + 4 + 1 + 3 + 5) ){ int nNew = p->nAlloc * 2; Fts5HashEntry *pNew; Fts5HashEntry **pp; @@ -250,9 +242,11 @@ int sqlite3Fts5HashWrite( /* If this is a new rowid, append the 4-byte size field for the previous ** entry, and the new rowid for this entry. */ if( iRowid!=p->iRowid ){ - p->nData += fts5PutNativeInt(&pPtr[p->nData], p->nData - p->iRowidOff); - p->iRowidOff = p->nData; - p->nData += sqlite3PutVarint(&pPtr[p->nData], iRowid); + assert( p->iSzPoslist>0 ); + fts5Put4ByteVarint(&pPtr[p->iSzPoslist], p->nData - p->iSzPoslist - 4); + p->nData += sqlite3PutVarint(&pPtr[p->nData], iRowid - p->iRowid); + p->iSzPoslist = p->nData; + p->nData += 4; p->iCol = 0; p->iPos = 0; p->iRowid = iRowid; @@ -379,28 +373,31 @@ int sqlite3Fts5HashIterate( while( pList ){ Fts5HashEntry *pNext = pList->pNext; if( rc==SQLITE_OK ){ + const int nSz = pList->nData - pList->iSzPoslist - 4; + const int nKey = strlen(pList->zKey); + i64 iRowid = 0; u8 *pPtr = (u8*)pList; - int nKey = strlen(pList->zKey); - int iOff = pList->iRowidOff; - int iEnd = sizeof(Fts5HashEntry) + nKey + 1; - int nByte = pList->nData - pList->iRowidOff; + int iOff = sizeof(Fts5HashEntry) + nKey + 1; + /* Fill in the final poslist size field */ + fts5Put4ByteVarint(&pPtr[pList->iSzPoslist], nSz); + + /* Issue the new-term callback */ rc = xTerm(pCtx, pList->zKey, nKey); - while( rc==SQLITE_OK && iOff ){ - int nVarint; - i64 iRowid; - nVarint = getVarint(&pPtr[iOff], (u64*)&iRowid); - rc = xEntry(pCtx, iRowid, &pPtr[iOff+nVarint], nByte-nVarint); - if( iOff==iEnd ){ - iOff = 0; - }else{ - nByte = fts5GetNativeU32(&pPtr[iOff-sizeof(int)]); - iOff = iOff - sizeof(int) - nByte; - } - } - if( rc==SQLITE_OK ){ - rc = xTermDone(pCtx); + + /* Issue the xEntry callbacks */ + while( rc==SQLITE_OK && iOffnData ){ + i64 iDelta; /* Rowid delta value */ + int nPoslist; /* Size of position list in bytes */ + iOff += getVarint(&pPtr[iOff], (u64*)&iDelta); + iRowid += iDelta; + iOff += fts5GetVarint32(&pPtr[iOff], nPoslist); + rc = xEntry(pCtx, iRowid, &pPtr[iOff], nPoslist); + iOff += nPoslist; } + + /* Issue the term-done callback */ + if( rc==SQLITE_OK ) rc = xTermDone(pCtx); } sqlite3_free(pList); pList = pNext; @@ -409,5 +406,3 @@ int sqlite3Fts5HashIterate( return rc; } - - diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 0cb2c2ee31..602046a302 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -44,7 +44,7 @@ #define FTS5_OPT_WORK_UNIT 1000 /* Number of leaf pages per optimize step */ #define FTS5_WORK_UNIT 64 /* Number of leaf pages in unit of work */ -#define FTS5_MIN_DLIDX_SIZE 4 /* Add dlidx if this many empty pages */ +#define FTS5_MIN_DLIDX_SIZE 4000 /* Add dlidx if this many empty pages */ /* ** Details: @@ -270,7 +270,6 @@ int sqlite3Fts5Corrupt() { return SQLITE_CORRUPT_VTAB; } typedef struct Fts5BtreeIter Fts5BtreeIter; typedef struct Fts5BtreeIterLevel Fts5BtreeIterLevel; typedef struct Fts5ChunkIter Fts5ChunkIter; -typedef struct Fts5Data Fts5Data; typedef struct Fts5DlidxIter Fts5DlidxIter; typedef struct Fts5MultiSegIter Fts5MultiSegIter; typedef struct Fts5NodeIter Fts5NodeIter; @@ -311,7 +310,7 @@ struct Fts5Index { }; struct Fts5DoclistIter { - int bAsc; + int bDesc; /* True for DESC order, false for ASC */ u8 *a; int n; int i; @@ -333,15 +332,6 @@ struct Fts5IndexIter { Fts5Buffer poslist; /* Buffer containing current poslist */ }; -/* -** A single record read from the %_data table. -*/ -struct Fts5Data { - u8 *p; /* Pointer to buffer containing record */ - int n; /* Size of record in bytes */ - int nRef; /* Ref count */ -}; - /* ** The contents of the "structure" record for each index are represented ** using an Fts5Structure record in memory. Which uses instances of the @@ -1483,6 +1473,11 @@ static void fts5DlidxIterFree(Fts5DlidxIter *pIter){ } } +static void fts5LeafHeader(Fts5Data *pLeaf, int *piRowid, int *piTerm){ + *piRowid = (int)fts5GetU16(&pLeaf->p[0]); + *piTerm = (int)fts5GetU16(&pLeaf->p[2]); +} + /* ** Load the next leaf page into the segment iterator. */ @@ -1503,8 +1498,15 @@ static void fts5SegIterNextPage( } /* -** Leave pIter->iLeafOffset as the offset to the size field of the first -** position list. The position list belonging to document pIter->iRowid. +** 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). */ static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){ u8 *a = pIter->pLeaf->p; /* Buffer to read data from */ @@ -1569,11 +1571,6 @@ static void fts5SegIterInit( } } -static void fts5LeafHeader(Fts5Data *pLeaf, int *piRowid, int *piTerm){ - *piRowid = (int)fts5GetU16(&pLeaf->p[0]); - *piTerm = (int)fts5GetU16(&pLeaf->p[2]); -} - /* ** This function is only ever called on iterators created by calls to ** Fts5IndexQuery() with the FTS5INDEX_QUERY_ASC flag set. @@ -1598,7 +1595,7 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){ if( i>=n ) break; i += getVarint(&a[i], (u64*)&iDelta); if( iDelta==0 ) break; - pIter->iRowid -= iDelta; + pIter->iRowid += iDelta; if( iRowidOffset>=pIter->nRowidOffset ){ int nNew = pIter->nRowidOffset + 8; @@ -1678,7 +1675,7 @@ static int fts5SegIterIsDelete( bRet = (pLeaf->p[pIter->iLeafOffset]==0x00); }else{ Fts5Data *pNew = fts5DataRead(p, FTS5_SEGMENT_ROWID( - pIter->iIdx, pIter->pSeg->iSegid, 0, pIter->iLeafPgno + pIter->iIdx, pIter->pSeg->iSegid, 0, pIter->iLeafPgno+1 )); if( pNew ){ bRet = (pNew->p[4]==0x00); @@ -1713,7 +1710,7 @@ static void fts5SegIterNext( iOff += fts5GetVarint32(&a[iOff], nPos); iOff += nPos; getVarint(&a[iOff], (u64*)&iDelta); - pIter->iRowid += iDelta; + pIter->iRowid -= iDelta; }else{ fts5SegIterReverseNewPage(p, pIter); } @@ -1748,7 +1745,7 @@ static void fts5SegIterNext( pIter->iLeafOffset += fts5GetVarint32(&a[iOff], nKeep); } }else{ - pIter->iRowid -= iDelta; + pIter->iRowid += iDelta; } }else{ iOff = 0; @@ -1922,7 +1919,7 @@ static void fts5SegIterSeekInit( int bGe = ((flags & FTS5INDEX_QUERY_PREFIX) && iIdx==0); int bDlidx = 0; /* True if there is a doclist-index */ - assert( bGe==0 || (flags & FTS5INDEX_QUERY_ASC)==0 ); + assert( bGe==0 || (flags & FTS5INDEX_QUERY_DESC)==0 ); assert( pTerm && nTerm ); memset(pIter, 0, sizeof(*pIter)); pIter->pSeg = pSeg; @@ -1980,13 +1977,13 @@ static void fts5SegIterSeekInit( if( p->rc==SQLITE_OK && bGe==0 ){ pIter->flags |= FTS5_SEGITER_ONETERM; if( pIter->pLeaf ){ - if( flags & FTS5INDEX_QUERY_ASC ){ + if( flags & FTS5INDEX_QUERY_DESC ){ pIter->flags |= FTS5_SEGITER_REVERSE; } if( bDlidx ){ fts5SegIterLoadDlidx(p, iIdx, pIter); } - if( flags & FTS5INDEX_QUERY_ASC ){ + if( flags & FTS5INDEX_QUERY_DESC ){ fts5SegIterReverse(p, iIdx, pIter); } } @@ -2042,7 +2039,7 @@ static int fts5MultiIterDoCompare(Fts5MultiSegIter *pIter, int iOut){ assert( i2>i1 ); assert( i2!=0 ); if( p1->iRowid==p2->iRowid ) return i2; - res = ((p1->iRowid < p2->iRowid)==pIter->bRev) ? -1 : +1; + res = ((p1->iRowid > p2->iRowid)==pIter->bRev) ? -1 : +1; } assert( res!=0 ); if( res<0 ){ @@ -2056,35 +2053,6 @@ static int fts5MultiIterDoCompare(Fts5MultiSegIter *pIter, int iOut){ return 0; } -/* -** Free the iterator object passed as the second argument. -*/ -static void fts5MultiIterFree(Fts5Index *p, Fts5MultiSegIter *pIter){ - if( pIter ){ - int i; - for(i=0; inSeg; i++){ - fts5SegIterClear(&pIter->aSeg[i]); - } - sqlite3_free(pIter); - } -} - -static void fts5MultiIterAdvanced( - Fts5Index *p, /* FTS5 backend to iterate within */ - Fts5MultiSegIter *pIter, /* Iterator to update aFirst[] array for */ - int iChanged, /* Index of sub-iterator just advanced */ - int iMinset /* Minimum entry in aFirst[] to set */ -){ - int i; - for(i=(pIter->nSeg+iChanged)/2; i>=iMinset && p->rc==SQLITE_OK; i=i/2){ - int iEq; - if( (iEq = fts5MultiIterDoCompare(pIter, i)) ){ - fts5SegIterNext(p, &pIter->aSeg[iEq]); - i = pIter->nSeg + iEq; - } - } -} - /* ** Move the seg-iter so that it points to the first rowid on page iLeafPgno. ** It is an error if leaf iLeafPgno contains no rowid. @@ -2170,6 +2138,36 @@ static void fts5SegIterNextFrom( } } + +/* +** Free the iterator object passed as the second argument. +*/ +static void fts5MultiIterFree(Fts5Index *p, Fts5MultiSegIter *pIter){ + if( pIter ){ + int i; + for(i=0; inSeg; i++){ + fts5SegIterClear(&pIter->aSeg[i]); + } + sqlite3_free(pIter); + } +} + +static void fts5MultiIterAdvanced( + Fts5Index *p, /* FTS5 backend to iterate within */ + Fts5MultiSegIter *pIter, /* Iterator to update aFirst[] array for */ + int iChanged, /* Index of sub-iterator just advanced */ + int iMinset /* Minimum entry in aFirst[] to set */ +){ + int i; + for(i=(pIter->nSeg+iChanged)/2; i>=iMinset && p->rc==SQLITE_OK; i=i/2){ + int iEq; + if( (iEq = fts5MultiIterDoCompare(pIter, i)) ){ + fts5SegIterNext(p, &pIter->aSeg[iEq]); + i = pIter->nSeg + iEq; + } + } +} + /* ** Move the iterator to the next entry. ** @@ -2248,7 +2246,7 @@ static void fts5MultiIterNew( pNew->nSeg = nSlot; pNew->aSeg = (Fts5SegIter*)&pNew[1]; pNew->aFirst = (u16*)&pNew->aSeg[nSlot]; - pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_ASC)); + pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC)); pNew->bSkipEmpty = bSkipEmpty; /* Initialize each of the component segment iterators. */ @@ -2328,8 +2326,8 @@ static void fts5MultiIterNextFrom( fts5MultiIterNext(p, pIter, 1, iMatch); if( fts5MultiIterEof(p, pIter) ) break; iRowid = fts5MultiIterRowid(pIter); - if( pIter->bRev==0 && iRowid<=iMatch ) break; - if( pIter->bRev!=0 && iRowid>=iMatch ) break; + if( pIter->bRev==0 && iRowid>=iMatch ) break; + if( pIter->bRev!=0 && iRowid<=iMatch ) break; } } @@ -2794,8 +2792,8 @@ static void fts5WriteAppendRowid( if( pWriter->bFirstRowidInDoclist || pWriter->bFirstRowidInPage ){ fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid); }else{ - assert( p->rc || iRowidiPrevRowid ); - fts5BufferAppendVarint(&p->rc, &pPage->buf, pWriter->iPrevRowid - iRowid); + assert( p->rc || iRowid>pWriter->iPrevRowid ); + fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid - pWriter->iPrevRowid); } pWriter->iPrevRowid = iRowid; pWriter->bFirstRowidInDoclist = 0; @@ -3711,10 +3709,10 @@ static void fts5DoclistIterNext(Fts5DoclistIter *pIter){ if( pIter->i ){ i64 iDelta; pIter->i += getVarint(&pIter->a[pIter->i], (u64*)&iDelta); - if( pIter->bAsc ){ - pIter->iRowid += iDelta; - }else{ + if( pIter->bDesc ){ pIter->iRowid -= iDelta; + }else{ + pIter->iRowid += iDelta; } }else{ pIter->i += getVarint(&pIter->a[pIter->i], (u64*)&pIter->iRowid); @@ -3729,13 +3727,13 @@ static void fts5DoclistIterNext(Fts5DoclistIter *pIter){ static void fts5DoclistIterInit( Fts5Buffer *pBuf, - int bAsc, + int bDesc, Fts5DoclistIter *pIter ){ memset(pIter, 0, sizeof(*pIter)); pIter->a = pBuf->p; pIter->n = pBuf->n; - pIter->bAsc = bAsc; + pIter->bDesc = bDesc; fts5DoclistIterNext(pIter); } @@ -3744,14 +3742,14 @@ static void fts5DoclistIterInit( */ static void fts5MergeAppendDocid( int *pRc, /* IN/OUT: Error code */ - int bAsc, + int bDesc, Fts5Buffer *pBuf, /* Buffer to write to */ i64 *piLastRowid, /* IN/OUT: Previous rowid written (if any) */ i64 iRowid /* Rowid to append */ ){ if( pBuf->n==0 ){ fts5BufferAppendVarint(pRc, pBuf, iRowid); - }else if( bAsc==0 ){ + }else if( bDesc ){ fts5BufferAppendVarint(pRc, pBuf, *piLastRowid - iRowid); }else{ fts5BufferAppendVarint(pRc, pBuf, iRowid - *piLastRowid); @@ -3769,7 +3767,7 @@ static void fts5MergeAppendDocid( */ static void fts5MergePrefixLists( Fts5Index *p, /* FTS5 backend object */ - int bAsc, + int bDesc, Fts5Buffer *p1, /* First list to merge */ Fts5Buffer *p2 /* Second list to merge */ ){ @@ -3782,21 +3780,21 @@ static void fts5MergePrefixLists( memset(&out, 0, sizeof(out)); memset(&tmp, 0, sizeof(tmp)); - fts5DoclistIterInit(p1, bAsc, &i1); - fts5DoclistIterInit(p2, bAsc, &i2); + fts5DoclistIterInit(p1, bDesc, &i1); + fts5DoclistIterInit(p2, bDesc, &i2); while( i1.aPoslist!=0 || i2.aPoslist!=0 ){ if( i2.aPoslist==0 || (i1.aPoslist && - ( (!bAsc && i1.iRowid>i2.iRowid) || (bAsc && i1.iRowidi2.iRowid) || (!bDesc && i1.iRowidrc, bAsc, &out, &iLastRowid, i1.iRowid); + fts5MergeAppendDocid(&p->rc, bDesc, &out, &iLastRowid, i1.iRowid); fts5BufferAppendVarint(&p->rc, &out, i1.nPoslist); fts5BufferAppendBlob(&p->rc, &out, i1.nPoslist, i1.aPoslist); fts5DoclistIterNext(&i1); } else if( i1.aPoslist==0 || i2.iRowid!=i1.iRowid ){ /* Copy entry from i2 */ - fts5MergeAppendDocid(&p->rc, bAsc, &out, &iLastRowid, i2.iRowid); + fts5MergeAppendDocid(&p->rc, bDesc, &out, &iLastRowid, i2.iRowid); fts5BufferAppendVarint(&p->rc, &out, i2.nPoslist); fts5BufferAppendBlob(&p->rc, &out, i2.nPoslist, i2.aPoslist); fts5DoclistIterNext(&i2); @@ -3809,7 +3807,7 @@ static void fts5MergePrefixLists( memset(&writer, 0, sizeof(writer)); /* Merge the two position lists. */ - fts5MergeAppendDocid(&p->rc, bAsc, &out, &iLastRowid, i2.iRowid); + fts5MergeAppendDocid(&p->rc, bDesc, &out, &iLastRowid, i2.iRowid); fts5BufferZero(&tmp); sqlite3Fts5PoslistReaderInit(-1, i1.aPoslist, i1.nPoslist, &r1); sqlite3Fts5PoslistReaderInit(-1, i2.aPoslist, i2.nPoslist, &r2); @@ -3847,7 +3845,7 @@ static void fts5BufferSwap(Fts5Buffer *p1, Fts5Buffer *p2){ static void fts5SetupPrefixIter( Fts5Index *p, /* Index to read from */ - int bAsc, /* True for "ORDER BY rowid ASC" */ + int bDesc, /* True for "ORDER BY rowid DESC" */ const u8 *pToken, /* Buffer containing prefix to match */ int nToken, /* Size of buffer pToken in bytes */ Fts5IndexIter *pIter /* Populate this object */ @@ -3878,7 +3876,7 @@ static void fts5SetupPrefixIter( if( nTerm0 - && ((!bAsc && iRowid>=iLastRowid) || (bAsc && iRowid<=iLastRowid)) + && ((!bDesc && iRowid<=iLastRowid) || (bDesc && iRowid>=iLastRowid)) ){ for(i=0; p->rc==SQLITE_OK && doclist.n; i++){ @@ -3887,14 +3885,14 @@ static void fts5SetupPrefixIter( fts5BufferSwap(&doclist, &aBuf[i]); fts5BufferZero(&doclist); }else{ - fts5MergePrefixLists(p, bAsc, &doclist, &aBuf[i]); + fts5MergePrefixLists(p, bDesc, &doclist, &aBuf[i]); fts5BufferZero(&aBuf[i]); } } } if( doclist.n==0 ){ fts5BufferAppendVarint(&p->rc, &doclist, iRowid); - }else if( bAsc==0 ){ + }else if( bDesc ){ fts5BufferAppendVarint(&p->rc, &doclist, iLastRowid - iRowid); }else{ fts5BufferAppendVarint(&p->rc, &doclist, iRowid - iLastRowid); @@ -3904,7 +3902,7 @@ static void fts5SetupPrefixIter( } for(i=0; ipDoclist = pDoclist; - fts5DoclistIterInit(&doclist, bAsc, pIter->pDoclist); + fts5DoclistIterInit(&doclist, bDesc, pIter->pDoclist); } } @@ -4273,8 +4271,8 @@ int sqlite3Fts5IndexQuery( ); } }else{ - int bAsc = (flags & FTS5INDEX_QUERY_ASC)!=0; - fts5SetupPrefixIter(p, bAsc, (const u8*)pToken, nToken, pRet); + int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0; + fts5SetupPrefixIter(p, bDesc, (const u8*)pToken, nToken, pRet); } } @@ -4321,8 +4319,8 @@ int sqlite3Fts5IterNext(Fts5IndexIter *pIter){ static void fts5DoclistIterNextFrom(Fts5DoclistIter *p, i64 iMatch){ do{ i64 iRowid = p->iRowid; - if( p->bAsc!=0 && iRowid>=iMatch ) break; - if( p->bAsc==0 && iRowid<=iMatch ) break; + if( p->bDesc==0 && iRowid>=iMatch ) break; + if( p->bDesc!=0 && iRowid<=iMatch ) break; fts5DoclistIterNext(p); }while( p->aPoslist ); } @@ -4602,7 +4600,7 @@ static int fts5DecodeDoclist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){ i64 iDelta; iOff += sqlite3GetVarint(&a[iOff], (u64*)&iDelta); if( iDelta==0 ) return iOff; - iDocid -= iDelta; + iDocid += iDelta; sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " rowid=%lld", iDocid); } } @@ -4692,7 +4690,6 @@ static void fts5DecodeFunction( } fts5DecodePoslist(&rc, &s, &a[4], iOff-4); - assert( iRowidOff==0 || iOff==iRowidOff ); if( iRowidOff ){ iOff += fts5DecodeDoclist(&rc, &s, &a[iOff], n-iOff); diff --git a/ext/fts5/test/fts5aa.test b/ext/fts5/test/fts5aa.test index 450539e889..cd3de2655b 100644 --- a/ext/fts5/test/fts5aa.test +++ b/ext/fts5/test/fts5aa.test @@ -185,7 +185,9 @@ for {set i 1} {$i <= 10} {incr i} { } execsql { INSERT INTO t1(t1) VALUES('integrity-check'); } } {} + if {$i==2} break } +#db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM t1_data} {puts $r} #------------------------------------------------------------------------- # @@ -312,7 +314,7 @@ do_execsql_test 13.1 { do_execsql_test 13.2 { SELECT rowid FROM t1 WHERE t1 MATCH 'o'; -} {2 1} +} {1 2} do_execsql_test 13.4 { DELETE FROM t1 WHERE rowid=2; diff --git a/ext/fts5/test/fts5ab.test b/ext/fts5/test/fts5ab.test index 79ebc7eaa5..d68240901e 100644 --- a/ext/fts5/test/fts5ab.test +++ b/ext/fts5/test/fts5ab.test @@ -30,11 +30,11 @@ do_execsql_test 1.0 { } do_execsql_test 1.1 { - SELECT * FROM t1; + SELECT * FROM t1 ORDER BY rowid DESC; } { forty five {one two} {three four} hello world } do_execsql_test 1.2 { - SELECT rowid FROM t1; + SELECT rowid FROM t1 ORDER BY rowid DESC; } {45 2 1} do_execsql_test 1.3 { @@ -90,7 +90,12 @@ foreach {tn expr res} { 9 y {6} 10 z {6} } { - do_execsql_test 2.7.$tn { SELECT rowid FROM t1 WHERE t1 MATCH $expr } $res + do_execsql_test 2.7.$tn.1 { + SELECT rowid FROM t1 WHERE t1 MATCH $expr ORDER BY rowid DESC + } $res + do_execsql_test 2.7.$tn.2 { + SELECT rowid FROM t1 WHERE t1 MATCH $expr ORDER BY rowid ASC + } [lsort -integer $res] } #------------------------------------------------------------------------- @@ -127,7 +132,7 @@ foreach {tn expr res} { 7 {"abashing abases abasement abaft abashing"} {8} } { do_execsql_test 3.2.$tn { - SELECT rowid FROM t1 WHERE t1 MATCH $expr + SELECT rowid FROM t1 WHERE t1 MATCH $expr ORDER BY rowid DESC } $res } @@ -145,7 +150,7 @@ foreach {tn expr res} { 7 {"abashing abases abasement abaft abashing"} {8} } { do_execsql_test 3.4.$tn { - SELECT rowid FROM t1 WHERE t1 MATCH $expr ORDER BY rowid ASC + SELECT rowid FROM t1 WHERE t1 MATCH $expr } $res } @@ -165,11 +170,11 @@ foreach {tn doc} [list \ do_execsql_test 4.3 { SELECT rowid FROM s1 WHERE s1 MATCH 'x' -} {2 1} +} {1 2} do_execsql_test 4.4 { SELECT rowid FROM s1 WHERE s1 MATCH '"a x"' -} {2 1} +} {1 2} #------------------------------------------------------------------------- # Check that a special case of segment promotion works. The case is where @@ -233,6 +238,23 @@ do_test 5.4 { fts5_level_segs s2 } {2 0} +#------------------------------------------------------------------------- +# +do_execsql_test 6.0 { + CREATE VIRTUAL TABLE s3 USING fts5(x); + BEGIN; + INSERT INTO s3 VALUES('a b c'); + INSERT INTO s3 VALUES('A B C'); +} + +do_execsql_test 6.1 { + SELECT rowid FROM s3 WHERE s3 MATCH 'a' +} {2 1} + +do_execsql_test 6.2 { + COMMIT; + SELECT rowid FROM s3 WHERE s3 MATCH 'a' +} {2 1} finish_test diff --git a/ext/fts5/test/fts5ac.test b/ext/fts5/test/fts5ac.test index 76f663ac5f..713e70dcd4 100644 --- a/ext/fts5/test/fts5ac.test +++ b/ext/fts5/test/fts5ac.test @@ -134,6 +134,7 @@ do_test 1.1 { foreach {id x y} $data { execsql { INSERT INTO xx(rowid, x, y) VALUES($id, $x, $y) } } + execsql { INSERT INTO xx(xx) VALUES('integrity-check') } } {} # Usage: @@ -253,7 +254,7 @@ proc instcompare {lhs rhs} { # where each element is a list of phrase matches in the # same form as returned by auxiliary scalar function fts5_test(). # -proc matchdata {bPos expr {bAsc 0}} { +proc matchdata {bPos expr {bAsc 1}} { set tclexpr [db one {SELECT fts5_expr_tcl($expr, 'nearset $cols', 'x', 'y')}] set res [list] @@ -307,6 +308,8 @@ sqlite3_fts5_create_function db fts5_test_poslist fts5_test_poslist # Test phrase queries. # foreach {tn phrase} { + 8 "c" + 1 "o" 2 "b q" 3 "e a e" @@ -400,8 +403,8 @@ do_execsql_test 6.integrity { } #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} + 1 {SELECT rowid FROM xx WHERE xx MATCH $expr} + 0 {SELECT rowid FROM xx WHERE xx MATCH $expr ORDER BY rowid DESC} } { foreach {tn expr} { 0.1 x diff --git a/ext/fts5/test/fts5ad.test b/ext/fts5/test/fts5ad.test index 9bc694f784..89a5078816 100644 --- a/ext/fts5/test/fts5ad.test +++ b/ext/fts5/test/fts5ad.test @@ -36,7 +36,7 @@ foreach {tn match res} { 4 {r*} {3 1} } { do_execsql_test 1.$tn { - SELECT rowid FROM yy WHERE yy MATCH $match + SELECT rowid FROM yy WHERE yy MATCH $match ORDER BY rowid DESC } $res } @@ -47,7 +47,7 @@ foreach {tn match res} { 8 {r*} {1 3} } { do_execsql_test 1.$tn { - SELECT rowid FROM yy WHERE yy MATCH $match ORDER BY rowid ASC + SELECT rowid FROM yy WHERE yy MATCH $match } $res } @@ -194,8 +194,8 @@ foreach {T create} { } foreach {bAsc sql} { - 0 {SELECT rowid FROM t1 WHERE t1 MATCH $prefix} - 1 {SELECT rowid FROM t1 WHERE t1 MATCH $prefix ORDER BY rowid ASC} + 1 {SELECT rowid FROM t1 WHERE t1 MATCH $prefix} + 0 {SELECT rowid FROM t1 WHERE t1 MATCH $prefix ORDER BY rowid DESC} } { foreach {tn prefix} { 1 {a*} 2 {ab*} 3 {abc*} 4 {abcd*} 5 {abcde*} diff --git a/ext/fts5/test/fts5ae.test b/ext/fts5/test/fts5ae.test index f327bc9207..c9c3fcce30 100644 --- a/ext/fts5/test/fts5ae.test +++ b/ext/fts5/test/fts5ae.test @@ -109,8 +109,8 @@ do_execsql_test 3.3 { SELECT rowid, fts5_test_poslist(t3) FROM t3 WHERE t3 MATCH 'a OR b AND c'; } { - 3 0.0.5 1 {0.0.6 1.0.9 0.0.10 0.0.12 1.0.15 2.1.2} + 3 0.0.5 } #------------------------------------------------------------------------- @@ -190,8 +190,8 @@ do_execsql_test 6.1 { do_execsql_test 6.2 { SELECT rowid, fts5_test_tokenize(t6) FROM t6 WHERE t6 MATCH 't*' } { - 2 {{horatio than are} {dreamt of in your philosophy}} 1 {{there are more} {things in heaven and earth}} + 2 {{horatio than are} {dreamt of in your philosophy}} } #------------------------------------------------------------------------- diff --git a/ext/fts5/test/fts5ak.test b/ext/fts5/test/fts5ak.test index 756ae0a898..4eb28324c9 100644 --- a/ext/fts5/test/fts5ak.test +++ b/ext/fts5/test/fts5ak.test @@ -40,19 +40,19 @@ do_execsql_test 1.1 { do_execsql_test 1.2 { SELECT highlight(ft1, 0, '[', ']') FROM ft1 WHERE ft1 MATCH 'e'; } { - {g d a [e] h a b c f j} - {i c c f a d g h j [e]} - {j f c [e] d a h j d b} - {i a d [e] g j g d a a} - {d c j d c j b c g [e]} {[e] j a [e] f h b f h h} + {d c j d c j b c g [e]} + {i a d [e] g j g d a a} + {j f c [e] d a h j d b} + {i c c f a d g h j [e]} + {g d a [e] h a b c f j} } do_execsql_test 1.3 { SELECT highlight(ft1, 0, '[', ']') FROM ft1 WHERE ft1 MATCH 'h + d'; } { - {j f [h d] g h i b d f} {[h d] b j c c g a c a} + {j f [h d] g h i b d f} } do_execsql_test 1.4 { @@ -64,12 +64,12 @@ do_execsql_test 1.4 { do_execsql_test 1.5 { SELECT highlight(ft1, 0, '[', ']') FROM ft1 WHERE ft1 MATCH 'e e e' } { - {g d a [e] h a b c f j} - {i c c f a d g h j [e]} - {j f c [e] d a h j d b} - {i a d [e] g j g d a a} - {d c j d c j b c g [e]} {[e] j a [e] f h b f h h} + {d c j d c j b c g [e]} + {i a d [e] g j g d a a} + {j f c [e] d a h j d b} + {i c c f a d g h j [e]} + {g d a [e] h a b c f j} } do_execsql_test 1.6 { @@ -133,9 +133,9 @@ do_execsql_test 3.1 { -- '[a b c d e]' SELECT highlight(ft, 0, '[', ']') FROM ft WHERE ft MATCH 'a+b+c AND c+d+e'; } { - {[a b c d e]} - {[a b c] [c d e]} {[a b c] x [c d e]} + {[a b c] [c d e]} + {[a b c d e]} } diff --git a/ext/fts5/test/fts5al.test b/ext/fts5/test/fts5al.test index 31d51713af..36402d6f6b 100644 --- a/ext/fts5/test/fts5al.test +++ b/ext/fts5/test/fts5al.test @@ -104,7 +104,7 @@ sqlite3_fts5_create_function db rowidtest rowidtest do_execsql_test 3.3.1 { SELECT rowidtest(t1) FROM t1 WHERE t1 MATCH 'q' -} {2 1} +} {1 2} proc insttest {cmd} { set res [list] @@ -118,15 +118,15 @@ sqlite3_fts5_create_function db insttest insttest do_execsql_test 3.4.1 { SELECT insttest(t1) FROM t1 WHERE t1 MATCH 'q' } { - {{0 0 5}} {{0 0 0}} + {{0 0 5}} } do_execsql_test 3.4.2 { SELECT insttest(t1) FROM t1 WHERE t1 MATCH 'r+e OR w' } { - {{0 0 2} {1 0 4}} {{1 0 1}} + {{0 0 2} {1 0 4}} } proc coltest {cmd} { @@ -137,7 +137,8 @@ sqlite3_fts5_create_function db coltest coltest do_execsql_test 3.5.1 { SELECT coltest(t1) FROM t1 WHERE t1 MATCH 'q' } { - {6 {y t r e w q}} {6 {q w e r t y}} + {6 {q w e r t y}} + {6 {y t r e w q}} } #------------------------------------------------------------------------- @@ -188,7 +189,7 @@ do_execsql_test 4.1.3 { WHERE t2 MATCH 'a' AND rank MATCH 'firstinst()' ORDER BY rank DESC } { - 5 103 9 102 6 9 10 8 3 6 2 4 7 0 1 0 + 5 103 9 102 6 9 10 8 3 6 2 4 1 0 7 0 } do_execsql_test 4.1.4 { @@ -202,14 +203,14 @@ do_execsql_test 4.1.4 { do_execsql_test 4.1.5 { SELECT rowid, rank FROM t2 WHERE t2 MATCH 'a' ORDER BY rank DESC } { - 5 103 9 102 6 9 10 8 3 6 2 4 7 0 1 0 + 5 103 9 102 6 9 10 8 3 6 2 4 1 0 7 0 } do_execsql_test 4.1.6 { INSERT INTO t2(t2, rank) VALUES('rank', 'firstinst ( ) '); SELECT rowid, rank FROM t2 WHERE t2 MATCH 'a' ORDER BY rank DESC } { - 5 103 9 102 6 9 10 8 3 6 2 4 7 0 1 0 + 5 103 9 102 6 9 10 8 3 6 2 4 1 0 7 0 } proc rowidplus {cmd ival} { @@ -257,14 +258,14 @@ do_execsql_test 4.3.2 { WHERE t3 MATCH 'a' AND rank MATCH 'rowidmod(4)' ORDER BY rank ASC } { - {a four} {a five} {a one} {a two} {a three} + {a four} {a one} {a five} {a two} {a three} } do_execsql_test 4.3.3 { SELECT *, rank FROM t3 WHERE t3 MATCH 'a' AND rank MATCH 'rowidmod(3)' ORDER BY rank ASC } { - {a three} 0 {a four} 1 {a one} 1 {a five} 2 {a two} 2 + {a three} 0 {a one} 1 {a four} 1 {a two} 2 {a five} 2 } diff --git a/ext/fts5/test/fts5content.test b/ext/fts5/test/fts5content.test index 948a4308b6..145fa4b6a9 100644 --- a/ext/fts5/test/fts5content.test +++ b/ext/fts5/test/fts5content.test @@ -26,38 +26,38 @@ do_execsql_test 1.1 { do_execsql_test 1.2 { SELECT rowid FROM f1 WHERE f1 MATCH 'o'; -} {2 1} +} {1 2} do_execsql_test 1.3 { INSERT INTO f1(a, b) VALUES('four', 'f o u r'); SELECT rowid FROM f1 WHERE f1 MATCH 'o'; -} {4 2 1} +} {1 2 4} do_execsql_test 1.4 { SELECT rowid, a, b FROM f1 WHERE f1 MATCH 'o'; -} {4 {} {} 2 {} {} 1 {} {}} +} {1 {} {} 2 {} {} 4 {} {}} do_execsql_test 1.5 { SELECT rowid, highlight(f1, 0, '[', ']') FROM f1 WHERE f1 MATCH 'o'; -} {4 {} 2 {} 1 {}} +} {1 {} 2 {} 4 {}} do_execsql_test 1.6 { SELECT rowid, highlight(f1, 0, '[', ']') IS NULL FROM f1 WHERE f1 MATCH 'o'; -} {4 1 2 1 1 1} +} {1 1 2 1 4 1} do_execsql_test 1.7 { SELECT rowid, snippet(f1, -1, '[', ']', '...', 5) IS NULL FROM f1 WHERE f1 MATCH 'o'; -} {4 1 2 1 1 1} +} {1 1 2 1 4 1} do_execsql_test 1.8 { SELECT rowid, snippet(f1, 1, '[', ']', '...', 5) IS NULL FROM f1 WHERE f1 MATCH 'o'; -} {4 1 2 1 1 1} +} {1 1 2 1 4 1} do_execsql_test 1.9 { SELECT rowid FROM f1; -} {4 3 2 1} +} {1 2 3 4} do_execsql_test 1.10 { SELECT * FROM f1; @@ -85,11 +85,11 @@ do_execsql_test 1.15 { do_execsql_test 1.16 { SELECT rowid FROM f1 WHERE f1 MATCH 'o'; -} {4 1} +} {1 4} do_execsql_test 1.17 { SELECT rowid FROM f1; -} {4 3 1} +} {1 3 4} #------------------------------------------------------------------------- # External content tables diff --git a/ext/fts5/test/fts5corrupt.test b/ext/fts5/test/fts5corrupt.test index 052563f779..57473afe65 100644 --- a/ext/fts5/test/fts5corrupt.test +++ b/ext/fts5/test/fts5corrupt.test @@ -53,23 +53,22 @@ db_restore_and_reopen #db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM t1_data} {puts $r} - #-------------------------------------------------------------------- +# do_execsql_test 2.0 { CREATE VIRTUAL TABLE t2 USING fts5(x); - INSERT INTO t2(t2, rank) VALUES('pgsz', 32); + INSERT INTO t2(t2, rank) VALUES('pgsz', 64); } +db func rnddoc fts5_rnddoc do_test 2.1 { - db transaction { - for {set i 0} {$i < 20} {incr i} { - execsql { INSERT INTO t2 VALUES('xxxxxxxxxx') } - } - for {set i 0} {$i < 20} {incr i} { - execsql { INSERT INTO t2 VALUES('xxxxxxxxxzzzz') } - } + for {set i 0} {$i < 500} {incr i} { + execsql { INSERT INTO t2 VALUES(rnddoc(50)) } + execsql { INSERT INTO t2(t2) VALUES('integrity-check') } } } {} -db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM t2_data} {puts $r} + +#-------------------------------------------------------------------- +# finish_test diff --git a/ext/fts5/test/fts5fault1.test b/ext/fts5/test/fts5fault1.test index 68aed258ec..838bf3cc4b 100644 --- a/ext/fts5/test/fts5fault1.test +++ b/ext/fts5/test/fts5fault1.test @@ -90,13 +90,13 @@ faultsim_save_and_close foreach {tn expr res} { 1 { dk } 7 2 { m f } 1 - 3 { f* } {10 9 8 6 5 4 3 1} - 4 { m OR f } {10 9 8 5 4 1} + 3 { f* } {1 3 4 5 6 8 9 10} + 4 { m OR f } {1 4 5 8 9 10} 5 { sn + gh } {5} 6 { "sn gh" } {5} 7 { NEAR(r a, 5) } {9} - 8 { m* f* } {10 9 8 6 4 1} - 9 { m* + f* } {8 1} + 8 { m* f* } {1 4 6 8 9 10} + 9 { m* + f* } {1 8} } { do_faultsim_test 4.$tn -prep { faultsim_restore_and_reopen @@ -302,7 +302,7 @@ db func rnddoc rnddoc do_test 8.0 { execsql { CREATE VIRTUAL TABLE x1 USING fts5(a) } set ::res [list] - for {set i 100} {$i>0} {incr i -1} { + for {set i 1} {$i<100} {incr i 1} { execsql { INSERT INTO x1 VALUES( rnddoc(50) ) } lappend ::res $i } diff --git a/ext/fts5/test/fts5rowid.test b/ext/fts5/test/fts5rowid.test index c33c9adea3..7ffd2977bf 100644 --- a/ext/fts5/test/fts5rowid.test +++ b/ext/fts5/test/fts5rowid.test @@ -172,7 +172,7 @@ do_test 5.0 { do_execsql_test 5.1 { SELECT rowid FROM x4 WHERE x4 MATCH 'a' -} {4 3 2 1} +} {1 2 3 4} set res [db one {SELECT count(*) FROM x4_data}] do_execsql_test 5.2 { diff --git a/manifest b/manifest index 9fdcf2e5e5..d15cc908b2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\scompression\sof\skeys\sstored\son\sinternal\ssegment\sb-tree\snodes\sby\sfts5. -D 2015-01-23T17:43:21.454 +C Have\sfts5\sstore\srowids\sin\sascending\sorder.\sQuery\sspeed\sis\svirtually\sthe\ssame\sregardless\sof\srowid\sorder,\sand\sascending\sorder\smakes\ssome\sinsert\soptimizations\seasier. +D 2015-01-24T19:57:03.097 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5407a688f4d77a05c18a8142be8ae5a2829dd610 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -104,15 +104,15 @@ F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7 F ext/fts3/unicode/mkunicode.tcl 4199cb887040ee3c3cd59a5171ddb0566904586e F ext/fts5/extract_api_docs.tcl 55a6d648d516f35d9a1e580ac00de27154e1904a -F ext/fts5/fts5.c 41b852b654f79f522668bc7ba292755fb261f855 +F ext/fts5/fts5.c f2e899fba27ca33c8897635752c4c83a40dcb18d F ext/fts5/fts5.h f931954065693898d26c51f23f1d27200184a69a -F ext/fts5/fts5Int.h 1d8f968b8ff71de15176acf8f4b14a2bdebcb6e3 +F ext/fts5/fts5Int.h e3b9344d8209c9639825c711662d5d039eb70322 F ext/fts5/fts5_aux.c 549aef152b0fd46020f5595d861b1fd60b3f9b4f F ext/fts5/fts5_buffer.c 32dd3c950392346ca69a0f1803501766c5c954f9 F ext/fts5/fts5_config.c e3421a76c2abd33a05ac09df0c97c64952d1e700 -F ext/fts5/fts5_expr.c 8a0e643768666dc2bffe74104141274809699808 -F ext/fts5/fts5_hash.c 7a87f9f2eae2216c710064821fa0621ac6a8ce7b -F ext/fts5/fts5_index.c dda2ed8dab9910aedd8de0169ca029c5336b9e42 +F ext/fts5/fts5_expr.c 473e3428a9a637fa6e61d64d8ca3796ec57a58e9 +F ext/fts5/fts5_hash.c 4ab952b75f27d5ed3ef0f3b4f7fa1464744483e8 +F ext/fts5/fts5_index.c b3e8e38c70178a638f4b0a183694db60ecde5366 F ext/fts5/fts5_storage.c f7c12c9f454b2a525827b3d85fd222789236f548 F ext/fts5/fts5_tcl.c 1293fac2bb26903fd3d5cdee59c5885ba7e620d5 F ext/fts5/fts5_tokenize.c 7c61d5c35c3449597bdeaa54dd48afe26852c7b0 @@ -120,30 +120,30 @@ F ext/fts5/fts5_unicode2.c 9c7dd640d1f014bf5c3ee029759adfbb4d7e95a9 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 8ddbbcbedab67101dc9a86fd5c39d78b0e06515f -F ext/fts5/test/fts5ab.test 3f3ad2fb9ed60a0df57b626fa6fe6ef41d4deee0 -F ext/fts5/test/fts5ac.test 48181b7c873da0e3b4a3316760fcb90d88e7fbd8 -F ext/fts5/test/fts5ad.test 3b01eec8516d5631909716514e2e585a45ef0eb1 -F ext/fts5/test/fts5ae.test 014d5be2f5f70407fb032d4f27704116254797c3 +F ext/fts5/test/fts5aa.test e77e28ac85c70891fc2603ff4b15de571eca628f +F ext/fts5/test/fts5ab.test 127769288519ed549c57d7e11628dbe5b9952ad5 +F ext/fts5/test/fts5ac.test 1dfa0751bcf32fd9cfaad1557b7729950e5cc930 +F ext/fts5/test/fts5ad.test 6c970531caf865b65f4e1dd9d6d43bd6ea37d754 +F ext/fts5/test/fts5ae.test 347c96db06aab23ff00cf6a6b4064a8dbb182e42 F ext/fts5/test/fts5af.test c2501ec2b61d6b179c305f5d2b8782ab3d4f832a F ext/fts5/test/fts5ag.test ec3e119b728196620a31507ef503c455a7a73505 F ext/fts5/test/fts5ah.test 17ba8e197a781ca10548b7260e39ed8269d24b93 F ext/fts5/test/fts5ai.test f20e53bbf0c55bc596f1fd47f2740dae028b8f37 F ext/fts5/test/fts5aj.test 05b569f5c16ea3098fb1984eec5cf50dbdaae5d8 -F ext/fts5/test/fts5ak.test dc7bcd087dea0451ec40bba173962a0ba3a1d8ce -F ext/fts5/test/fts5al.test 633fdb3d974629d01ba7734d180dbc2ad8ed772a +F ext/fts5/test/fts5ak.test 7b8c5df96df599293f920b7e5521ebc79f647592 +F ext/fts5/test/fts5al.test 6a5717faaf7f1e0e866360022d284903f3a4eede F ext/fts5/test/fts5auxdata.test c69b86092bf1a157172de5f9169731af3403179b -F ext/fts5/test/fts5content.test 4234e0b11e003fe1e80472aa637f70464396fdd0 -F ext/fts5/test/fts5corrupt.test b81ed310018ddffb34da7802f74018d94a2b3961 +F ext/fts5/test/fts5content.test 8dc302fccdff834d946497e9d862750ea87d4517 +F ext/fts5/test/fts5corrupt.test 78eb076867e750a013b46b3bc06065870bc93c22 F ext/fts5/test/fts5ea.test 04695560a444fcc00c3c4f27783bdcfbf71f030c F ext/fts5/test/fts5eb.test 728a1f23f263548f5c29b29dfb851b5f2dbe723e -F ext/fts5/test/fts5fault1.test f9bafb61b40061ad19b61d15003c5faeea4a57b5 +F ext/fts5/test/fts5fault1.test fbd8612889234849ff041f5b36f8e390feeed46e F ext/fts5/test/fts5near.test 3f9f64e16cac82725d03d4e04c661090f0b3b947 F ext/fts5/test/fts5optimize.test 0028c90a7817d3e576d1148fc8dff17d89054e54 F ext/fts5/test/fts5porter.test 50322599823cb8080a99f0ec0c39f7d0c12bcb5e F ext/fts5/test/fts5prefix.test 4610dfba4460d92f23a8014874a46493f1be77b5 F ext/fts5/test/fts5rebuild.test 2a5e98205393487b4a732c8290999af7c0b907b4 -F ext/fts5/test/fts5rowid.test db482328fe9bf78bb6a09f2dbf055e2caeaac00a +F ext/fts5/test/fts5rowid.test a1b2a6d76648c734c1aab11ee1a619067e8d90e6 F ext/fts5/test/fts5tokenizer.test b34ae592db66f6e89546d791ce1f905ba0b3395c F ext/fts5/test/fts5unicode.test 79b3e34eb29ce4929628aa514a40cb467fdabe4d F ext/fts5/test/fts5unicode2.test 64a5267fd6082fcb46439892ebd0cbaa5c38acee @@ -1283,7 +1283,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 939b7a5de25e064bdf08e03864c35ab718da6f6f -R 7096f8b96e0f85e1680222eb9ee6721b +P 51444f67c0cc58a3023eb1cd78e7cf889da6c80f +R bde0099a6ffad2afb653ac6add38295f U dan -Z 0515045012673cdccd49d82241057133 +Z 8b04510bfa3b18ba6ca879f4b4c9a36e diff --git a/manifest.uuid b/manifest.uuid index 324db551da..fb905f2048 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -51444f67c0cc58a3023eb1cd78e7cf889da6c80f \ No newline at end of file +5206ca6005bfa9dfc7346d4b89430c9748d32c10 \ No newline at end of file