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
This commit is contained in:
parent
641cb4360a
commit
8ac3025419
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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*);
|
||||
|
@ -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 && iRowid<iLast) ){
|
||||
if( (bDesc==0 && iLast>iRowid) || (bDesc && iLast<iRowid) ){
|
||||
sqlite3Fts5IterNextFrom(pIter, iLast);
|
||||
if( sqlite3Fts5IterEof(pIter) ){
|
||||
*pbEof = 1;
|
||||
return 1;
|
||||
}
|
||||
iRowid = sqlite3Fts5IterRowid(pIter);
|
||||
assert( (bAsc==0 && iRowid<=iLast) || (bAsc==1 && iRowid>=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->iRowid<p2->iRowid ) 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;
|
||||
|
@ -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 && iOff<pList->nData ){
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -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; i<pIter->nSeg; 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; i<pIter->nSeg; 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 || iRowid<pWriter->iPrevRowid );
|
||||
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.iRowid<i2.iRowid) )
|
||||
( (bDesc && i1.iRowid>i2.iRowid) || (!bDesc && i1.iRowid<i2.iRowid) )
|
||||
)){
|
||||
/* Copy entry from i1 */
|
||||
fts5MergeAppendDocid(&p->rc, 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( nTerm<nToken || memcmp(pToken, pTerm, nToken) ) break;
|
||||
|
||||
if( doclist.n>0
|
||||
&& ((!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; i<nBuf; i++){
|
||||
fts5MergePrefixLists(p, bAsc, &doclist, &aBuf[i]);
|
||||
fts5MergePrefixLists(p, bDesc, &doclist, &aBuf[i]);
|
||||
fts5BufferFree(&aBuf[i]);
|
||||
}
|
||||
fts5MultiIterFree(p, p1);
|
||||
@ -3914,7 +3912,7 @@ static void fts5SetupPrefixIter(
|
||||
fts5BufferFree(&doclist);
|
||||
}else{
|
||||
pIter->pDoclist = 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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 <phrase X matches> 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
|
||||
|
@ -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*}
|
||||
|
@ -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}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
@ -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]}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
42
manifest
42
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
|
||||
|
@ -1 +1 @@
|
||||
51444f67c0cc58a3023eb1cd78e7cf889da6c80f
|
||||
5206ca6005bfa9dfc7346d4b89430c9748d32c10
|
Loading…
Reference in New Issue
Block a user