Changes to fts3 to avoid flushing data to disk within a SELECT statement.
FossilOrigin-Name: 48c0db0eb2d134bb302bb5eca6beb0ec46736257
This commit is contained in:
parent
0edb3cf53d
commit
b893721a45
@ -426,35 +426,30 @@ int sqlite3Fts3VarintLen(sqlite3_uint64 v){
|
||||
** 'xyz' becomes xyz
|
||||
** [pqr] becomes pqr
|
||||
** `mno` becomes mno
|
||||
**
|
||||
*/
|
||||
void sqlite3Fts3Dequote(char *z){
|
||||
char quote;
|
||||
int i, j;
|
||||
char quote; /* Quote character (if any ) */
|
||||
|
||||
quote = z[0];
|
||||
switch( quote ){
|
||||
case '\'': break;
|
||||
case '"': break;
|
||||
case '`': break; /* For MySQL compatibility */
|
||||
case '[': quote = ']'; break; /* For MS SqlServer compatibility */
|
||||
default: return;
|
||||
}
|
||||
if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){
|
||||
int iIn = 1; /* Index of next byte to read from input */
|
||||
int iOut = 0; /* Index of next byte to write to output */
|
||||
|
||||
i = 1;
|
||||
j = 0;
|
||||
while( ALWAYS(z[i]) ){
|
||||
if( z[i]==quote ){
|
||||
if( z[i+1]==quote ){
|
||||
z[j++] = quote;
|
||||
i += 2;
|
||||
/* If the first byte was a '[', then the close-quote character is a ']' */
|
||||
if( quote=='[' ) quote = ']';
|
||||
|
||||
while( ALWAYS(z[iIn]) ){
|
||||
if( z[iIn]==quote ){
|
||||
if( z[iIn+1]!=quote ) break;
|
||||
z[iOut++] = quote;
|
||||
iIn += 2;
|
||||
}else{
|
||||
break;
|
||||
z[iOut++] = z[iIn++];
|
||||
}
|
||||
}else{
|
||||
z[j++] = z[i++];
|
||||
}
|
||||
z[iOut] = '\0';
|
||||
}
|
||||
z[j] = 0;
|
||||
}
|
||||
|
||||
static void fts3GetDeltaVarint(char **pp, sqlite3_int64 *pVal){
|
||||
@ -1594,13 +1589,21 @@ static int fts3TermSelect(
|
||||
int i;
|
||||
TermSelect tsc;
|
||||
Fts3SegFilter filter; /* Segment term filter configuration */
|
||||
Fts3SegReader **apSegment = 0; /* Array of segments to read data from */
|
||||
Fts3SegReader **apSegment; /* Array of segments to read data from */
|
||||
int nSegment = 0; /* Size of apSegment array */
|
||||
int nAlloc = 0; /* Allocated size of segment array */
|
||||
int nAlloc = 16; /* Allocated size of segment array */
|
||||
int rc; /* Return code */
|
||||
sqlite3_stmt *pStmt; /* SQL statement to scan %_segdir table */
|
||||
int iAge = 0; /* Used to assign ages to segments */
|
||||
|
||||
apSegment = (Fts3SegReader **)sqlite3_malloc(sizeof(Fts3SegReader*)*nAlloc);
|
||||
if( !apSegment ) return SQLITE_NOMEM;
|
||||
rc = sqlite3Fts3SegReaderPending(p, zTerm, nTerm, isPrefix, &apSegment[0]);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
if( apSegment[0] ){
|
||||
nSegment = 1;
|
||||
}
|
||||
|
||||
/* Loop through the entire %_segdir table. For each segment, create a
|
||||
** Fts3SegReader to iterate through the subset of the segment leaves
|
||||
** that may contain a term that matches zTerm/nTerm. For non-prefix
|
||||
@ -1717,8 +1720,6 @@ static int fts3PhraseSelect(
|
||||
int iCol = pPhrase->iColumn;
|
||||
int isTermPos = (pPhrase->nToken>1 || isReqPos);
|
||||
|
||||
assert( p->nPendingData==0 );
|
||||
|
||||
for(ii=0; ii<pPhrase->nToken; ii++){
|
||||
struct PhraseToken *pTok = &pPhrase->aToken[ii];
|
||||
char *z = pTok->z; /* Next token of the phrase */
|
||||
@ -1934,8 +1935,6 @@ static int fts3FilterMethod(
|
||||
if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
rc = sqlite3Fts3PendingTermsFlush(p);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
rc = sqlite3Fts3ExprParse(p->pTokenizer, p->azColumn, p->nColumn,
|
||||
iCol, zQuery, -1, &pCsr->pExpr
|
||||
@ -1991,21 +1990,22 @@ static int fts3ColumnMethod(
|
||||
/* The column value supplied by SQLite must be in range. */
|
||||
assert( iCol>=0 && iCol<=p->nColumn+1 );
|
||||
|
||||
rc = fts3CursorSeek(pCsr);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( iCol==p->nColumn+1 ){
|
||||
/* This call is a request for the "docid" column. Since "docid" is an
|
||||
** alias for "rowid", use the xRowid() method to obtain the value.
|
||||
*/
|
||||
sqlite3_int64 iRowid;
|
||||
rc = fts3RowidMethod(pCursor, &iRowid);
|
||||
sqlite3_result_int64(pContext, iRowid);
|
||||
}else if( iCol==p->nColumn ){
|
||||
/* The extra column whose name is the same as the table.
|
||||
** Return a blob which is a pointer to the cursor.
|
||||
*/
|
||||
sqlite3_result_blob(pContext, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
|
||||
}else{
|
||||
if( iCol==p->nColumn+1 ){
|
||||
/* This call is a request for the "docid" column. Since "docid" is an
|
||||
** alias for "rowid", use the xRowid() method to obtain the value.
|
||||
*/
|
||||
sqlite3_int64 iRowid;
|
||||
rc = fts3RowidMethod(pCursor, &iRowid);
|
||||
sqlite3_result_int64(pContext, iRowid);
|
||||
}else if( iCol==p->nColumn ){
|
||||
/* The extra column whose name is the same as the table.
|
||||
** Return a blob which is a pointer to the cursor.
|
||||
*/
|
||||
sqlite3_result_blob(pContext, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
rc = fts3CursorSeek(pCsr);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_result_value(pContext, sqlite3_column_value(pCsr->pStmt, iCol+1));
|
||||
}
|
||||
}
|
||||
|
@ -225,6 +225,7 @@ void sqlite3Fts3PendingTermsClear(Fts3Table *);
|
||||
int sqlite3Fts3Optimize(Fts3Table *);
|
||||
int sqlite3Fts3SegReaderNew(Fts3Table *,int, sqlite3_int64,
|
||||
sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**);
|
||||
int sqlite3Fts3SegReaderPending(Fts3Table*,const char*,int,int,Fts3SegReader**);
|
||||
void sqlite3Fts3SegReaderFree(Fts3Table *, Fts3SegReader *);
|
||||
int sqlite3Fts3SegReaderIterate(
|
||||
Fts3Table *, Fts3SegReader **, int, Fts3SegFilter *,
|
||||
|
@ -279,13 +279,12 @@ static void fts3RemoveElementByHash(
|
||||
}
|
||||
}
|
||||
|
||||
/* Attempt to locate an element of the hash table pH with a key
|
||||
** that matches pKey,nKey. Return the data for this element if it is
|
||||
** found, or NULL if there is no match.
|
||||
*/
|
||||
void *sqlite3Fts3HashFind(const Fts3Hash *pH, const void *pKey, int nKey){
|
||||
int h; /* A hash on key */
|
||||
Fts3HashElem *elem; /* The element that matches key */
|
||||
Fts3HashElem *sqlite3Fts3HashFindElem(
|
||||
const Fts3Hash *pH,
|
||||
const void *pKey,
|
||||
int nKey
|
||||
){
|
||||
int h; /* A hash on key */
|
||||
int (*xHash)(const void*,int); /* The hash function */
|
||||
|
||||
if( pH==0 || pH->ht==0 ) return 0;
|
||||
@ -293,8 +292,19 @@ void *sqlite3Fts3HashFind(const Fts3Hash *pH, const void *pKey, int nKey){
|
||||
assert( xHash!=0 );
|
||||
h = (*xHash)(pKey,nKey);
|
||||
assert( (pH->htsize & (pH->htsize-1))==0 );
|
||||
elem = fts3FindElementByHash(pH,pKey,nKey, h & (pH->htsize-1));
|
||||
return elem ? elem->data : 0;
|
||||
return fts3FindElementByHash(pH,pKey,nKey, h & (pH->htsize-1));
|
||||
}
|
||||
|
||||
/*
|
||||
** Attempt to locate an element of the hash table pH with a key
|
||||
** that matches pKey,nKey. Return the data for this element if it is
|
||||
** found, or NULL if there is no match.
|
||||
*/
|
||||
void *sqlite3Fts3HashFind(const Fts3Hash *pH, const void *pKey, int nKey){
|
||||
Fts3HashElem *pElem; /* The element that matches key (if any) */
|
||||
|
||||
pElem = sqlite3Fts3HashFindElem(pH, pKey, nKey);
|
||||
return pElem ? pElem->data : 0;
|
||||
}
|
||||
|
||||
/* Insert an element into the hash table pH. The key is pKey,nKey
|
||||
|
@ -75,14 +75,16 @@ void sqlite3Fts3HashInit(Fts3Hash *pNew, char keyClass, char copyKey);
|
||||
void *sqlite3Fts3HashInsert(Fts3Hash*, const void *pKey, int nKey, void *pData);
|
||||
void *sqlite3Fts3HashFind(const Fts3Hash*, const void *pKey, int nKey);
|
||||
void sqlite3Fts3HashClear(Fts3Hash*);
|
||||
Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const void *, int);
|
||||
|
||||
/*
|
||||
** Shorthand for the functions above
|
||||
*/
|
||||
#define fts3HashInit sqlite3Fts3HashInit
|
||||
#define fts3HashInsert sqlite3Fts3HashInsert
|
||||
#define fts3HashFind sqlite3Fts3HashFind
|
||||
#define fts3HashClear sqlite3Fts3HashClear
|
||||
#define fts3HashInit sqlite3Fts3HashInit
|
||||
#define fts3HashInsert sqlite3Fts3HashInsert
|
||||
#define fts3HashFind sqlite3Fts3HashFind
|
||||
#define fts3HashClear sqlite3Fts3HashClear
|
||||
#define fts3HashFindElem sqlite3Fts3HashFindElem
|
||||
|
||||
/*
|
||||
** Macros for looping over all elements of a hash table. The idiom is
|
||||
|
@ -30,7 +30,7 @@ typedef struct SegmentWriter SegmentWriter;
|
||||
|
||||
/*
|
||||
** Data structure used while accumulating terms in the pending-terms hash
|
||||
** table. The hash table entry maps from term (a string) to a malloced
|
||||
** table. The hash table entry maps from term (a string) to a malloc'd
|
||||
** instance of this structure.
|
||||
*/
|
||||
struct PendingList {
|
||||
@ -52,15 +52,22 @@ struct PendingList {
|
||||
** sqlite3Fts3SegReaderNew()
|
||||
** sqlite3Fts3SegReaderFree()
|
||||
** sqlite3Fts3SegReaderIterate()
|
||||
**
|
||||
** Methods used to manipulate Fts3SegReader structures:
|
||||
**
|
||||
** fts3SegReaderNext()
|
||||
** fts3SegReaderFirstDocid()
|
||||
** fts3SegReaderNextDocid()
|
||||
*/
|
||||
struct Fts3SegReader {
|
||||
int iIdx; /* Index within level */
|
||||
int iIdx; /* Index within level, or 0x7FFFFFFF for PT */
|
||||
sqlite3_int64 iStartBlock;
|
||||
sqlite3_int64 iEndBlock;
|
||||
sqlite3_stmt *pStmt; /* SQL Statement to access leaf nodes */
|
||||
char *aNode; /* Pointer to node data (or NULL) */
|
||||
int nNode; /* Size of buffer at aNode (or 0) */
|
||||
int nTermAlloc; /* Allocated size of zTerm buffer */
|
||||
Fts3HashElem **ppNextElem;
|
||||
|
||||
/* Variables set by fts3SegReaderNext(). These may be read directly
|
||||
** by the caller. They are valid from the time SegmentReaderNew() returns
|
||||
@ -77,6 +84,8 @@ struct Fts3SegReader {
|
||||
sqlite3_int64 iDocid;
|
||||
};
|
||||
|
||||
#define fts3SegReaderIsPending(p) ((p)->ppNextElem!=0)
|
||||
|
||||
/*
|
||||
** An instance of this structure is used to create a segment b-tree in the
|
||||
** database. The internal details of this type are only accessed by the
|
||||
@ -728,6 +737,20 @@ static int fts3SegReaderNext(Fts3SegReader *pReader){
|
||||
|
||||
if( !pNext || pNext>=&pReader->aNode[pReader->nNode] ){
|
||||
int rc;
|
||||
if( fts3SegReaderIsPending(pReader) ){
|
||||
Fts3HashElem *pElem = *(pReader->ppNextElem);
|
||||
if( pElem==0 ){
|
||||
pReader->aNode = 0;
|
||||
}else{
|
||||
PendingList *pList = (PendingList *)fts3HashData(pElem);
|
||||
pReader->zTerm = (char *)fts3HashKey(pElem);
|
||||
pReader->nTerm = fts3HashKeysize(pElem);
|
||||
pReader->nNode = pReader->nDoclist = pList->nData;
|
||||
pReader->aNode = pReader->aDoclist = pList->aData;
|
||||
pReader->ppNextElem++;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
if( !pReader->pStmt ){
|
||||
pReader->aNode = 0;
|
||||
return SQLITE_OK;
|
||||
@ -837,7 +860,9 @@ void sqlite3Fts3SegReaderFree(Fts3Table *p, Fts3SegReader *pReader){
|
||||
sqlite3_reset(pReader->pStmt);
|
||||
p->aLeavesStmt[p->nLeavesStmt++] = pReader->pStmt;
|
||||
}
|
||||
sqlite3_free(pReader->zTerm);
|
||||
if( !fts3SegReaderIsPending(pReader) ){
|
||||
sqlite3_free(pReader->zTerm);
|
||||
}
|
||||
sqlite3_free(pReader);
|
||||
}
|
||||
}
|
||||
@ -934,6 +959,97 @@ int sqlite3Fts3SegReaderNew(
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This is a comparison function used as a qsort() callback when sorting
|
||||
** an array of pending terms by term. This occurs as part of flushing
|
||||
** the contents of the pending-terms hash table to the database.
|
||||
*/
|
||||
static int fts3CompareElemByTerm(const void *lhs, const void *rhs){
|
||||
char *z1 = fts3HashKey(*(Fts3HashElem **)lhs);
|
||||
char *z2 = fts3HashKey(*(Fts3HashElem **)rhs);
|
||||
int n1 = fts3HashKeysize(*(Fts3HashElem **)lhs);
|
||||
int n2 = fts3HashKeysize(*(Fts3HashElem **)rhs);
|
||||
|
||||
int n = (n1<n2 ? n1 : n2);
|
||||
int c = memcmp(z1, z2, n);
|
||||
if( c==0 ){
|
||||
c = n1 - n2;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is used to allocate an Fts3SegReader that iterates through
|
||||
** a subset of the terms stored in the Fts3Table.pendingTerms array.
|
||||
*/
|
||||
int sqlite3Fts3SegReaderPending(
|
||||
Fts3Table *p, /* Virtual table handle */
|
||||
const char *zTerm, /* Term to search for */
|
||||
int nTerm, /* Size of buffer zTerm */
|
||||
int isPrefix, /* True for a term-prefix query */
|
||||
Fts3SegReader **ppReader /* OUT: SegReader for pending-terms */
|
||||
){
|
||||
Fts3SegReader *pReader = 0; /* Fts3SegReader object to return */
|
||||
Fts3HashElem **aElem = 0; /* Array of term hash entries to scan */
|
||||
int nElem = 0; /* Size of array at aElem */
|
||||
int rc = SQLITE_OK; /* Return Code */
|
||||
|
||||
if( isPrefix ){
|
||||
Fts3HashElem *pE = 0; /* Iterator variable */
|
||||
|
||||
for(pE=fts3HashFirst(&p->pendingTerms); pE; pE=fts3HashNext(pE)){
|
||||
char *zKey = (char *)fts3HashKey(pE);
|
||||
int nKey = fts3HashKeysize(pE);
|
||||
if( nKey>=nTerm && 0==memcmp(zKey, zTerm, nTerm) ){
|
||||
int nByte = (1+nElem * sizeof(Fts3HashElem *));
|
||||
Fts3HashElem **aElem2 = (Fts3HashElem **)sqlite3_realloc(aElem, nByte);
|
||||
if( !aElem2 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
nElem = 0;
|
||||
break;
|
||||
}
|
||||
aElem = aElem2;
|
||||
aElem[nElem++] = pE;
|
||||
}
|
||||
}
|
||||
|
||||
/* If more than one term matches the prefix, sort the Fts3HashElem
|
||||
** objects in term order using qsort(). This uses the same comparison
|
||||
** callback as is used when flushing terms to disk.
|
||||
*/
|
||||
if( nElem>1 ){
|
||||
qsort(aElem, nElem, sizeof(Fts3HashElem *), fts3CompareElemByTerm);
|
||||
}
|
||||
|
||||
}else{
|
||||
Fts3HashElem *pE = fts3HashFindElem(&p->pendingTerms, zTerm, nTerm);
|
||||
if( pE ){
|
||||
aElem = &pE;
|
||||
nElem = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if( nElem>0 ){
|
||||
int nByte = sizeof(Fts3SegReader) + (nElem+1)*sizeof(Fts3HashElem *);
|
||||
pReader = (Fts3SegReader *)sqlite3_malloc(nByte);
|
||||
if( !pReader ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
memset(pReader, 0, nByte);
|
||||
pReader->iIdx = 0x7FFFFFFF;
|
||||
pReader->ppNextElem = (Fts3HashElem **)&pReader[1];
|
||||
memcpy(pReader->ppNextElem, aElem, nElem*sizeof(Fts3HashElem *));
|
||||
fts3SegReaderNext(pReader);
|
||||
}
|
||||
}
|
||||
|
||||
if( isPrefix ){
|
||||
sqlite3_free(aElem);
|
||||
}
|
||||
*ppReader = pReader;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** The second argument to this function is expected to be a statement of
|
||||
@ -977,7 +1093,7 @@ static int fts3SegReaderNew(
|
||||
**
|
||||
** 1) EOF is greater than not EOF.
|
||||
**
|
||||
** 2) The current terms (if any) are compared with memcmp(). If one
|
||||
** 2) The current terms (if any) are compared using memcmp(). If one
|
||||
** term is a prefix of another, the longer term is considered the
|
||||
** larger.
|
||||
**
|
||||
@ -1790,8 +1906,7 @@ int sqlite3Fts3SegReaderIterate(
|
||||
Fts3SegReader *pSeg = apSegment[i];
|
||||
while( fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 ){
|
||||
rc = fts3SegReaderNext(pSeg);
|
||||
if( rc!=SQLITE_OK ) goto finished;
|
||||
}
|
||||
if( rc!=SQLITE_OK ) goto finished; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1849,9 +1964,9 @@ int sqlite3Fts3SegReaderIterate(
|
||||
sqlite3_int64 iDocid = apSegment[0]->iDocid;
|
||||
fts3SegReaderNextDocid(apSegment[0], &pList, &nList);
|
||||
j = 1;
|
||||
while( j<nMerge
|
||||
&& apSegment[j]->pOffsetList
|
||||
&& apSegment[j]->iDocid==iDocid
|
||||
while( j<nMerge
|
||||
&& apSegment[j]->pOffsetList
|
||||
&& apSegment[j]->iDocid==iDocid
|
||||
){
|
||||
fts3SegReaderNextDocid(apSegment[j], 0, 0);
|
||||
j++;
|
||||
@ -2009,25 +2124,6 @@ static int fts3SegmentMerge(Fts3Table *p, int iLevel){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This is a comparison function used as a qsort() callback when sorting
|
||||
** an array of pending terms by term. This occurs as part of flushing
|
||||
** the contents of the pending-terms hash table to the database.
|
||||
*/
|
||||
static int qsortCompare(const void *lhs, const void *rhs){
|
||||
char *z1 = fts3HashKey(*(Fts3HashElem **)lhs);
|
||||
char *z2 = fts3HashKey(*(Fts3HashElem **)rhs);
|
||||
int n1 = fts3HashKeysize(*(Fts3HashElem **)lhs);
|
||||
int n2 = fts3HashKeysize(*(Fts3HashElem **)rhs);
|
||||
|
||||
int n = (n1<n2 ? n1 : n2);
|
||||
int c = memcmp(z1, z2, n);
|
||||
if( c==0 ){
|
||||
c = n1 - n2;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Flush the contents of pendingTerms to a level 0 segment.
|
||||
@ -2070,7 +2166,7 @@ int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
|
||||
** Also, should we be using qsort()?
|
||||
*/
|
||||
if( nElem>1 ){
|
||||
qsort(apElem, nElem, sizeof(Fts3HashElem *), qsortCompare);
|
||||
qsort(apElem, nElem, sizeof(Fts3HashElem *), fts3CompareElemByTerm);
|
||||
}
|
||||
|
||||
|
||||
|
36
manifest
36
manifest
@ -1,8 +1,5 @@
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA1
|
||||
|
||||
C Only\sdeclare\sthe\ssqlite3_mutex_held()\sand\ssqlite3_mutex_notheld()\sinterfaces\nin\sthe\sheader\sfile\sif\sNDEBUG\sis\snot\sdefined.
|
||||
D 2009-12-10T01:17:29
|
||||
C Changes\sto\sfts3\sto\savoid\sflushing\sdata\sto\sdisk\swithin\sa\sSELECT\sstatement.
|
||||
D 2009-12-10T16:04:26
|
||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||
F Makefile.in c5827ead754ab32b9585487177c93bb00b9497b3
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@ -59,19 +56,19 @@ F ext/fts2/mkfts2amal.tcl 974d5d438cb3f7c4a652639262f82418c1e4cff0
|
||||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||
F ext/fts3/README.tokenizers 998756696647400de63d5ba60e9655036cb966e9
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c 6e24afa93ecb3395b0e9467ca2b44fa7f66f4fdc
|
||||
F ext/fts3/fts3.c f72d7fdb5cca933a9311037e63610a182d9369b4
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h 36f8e6d6fafa6d71a48e1810095e1e58fd55b199
|
||||
F ext/fts3/fts3Int.h 1419e2973b44ee78f0ae8f7e03abfa2bdaf14f54
|
||||
F ext/fts3/fts3_expr.c fcf6812dbfd9cb9a2cabaf50e741411794f83e7e
|
||||
F ext/fts3/fts3_hash.c 18feef38fca216992725e9eae775a0c7735e6724
|
||||
F ext/fts3/fts3_hash.h d410ff2c93c81a56b927fcf07b2099ccbfa7a479
|
||||
F ext/fts3/fts3_hash.c 3c8f6387a4a7f5305588b203fa7c887d753e1f1c
|
||||
F ext/fts3/fts3_hash.h 8331fb2206c609f9fc4c4735b9ab5ad6137c88ec
|
||||
F ext/fts3/fts3_icu.c ac494aed69835008185299315403044664bda295
|
||||
F ext/fts3/fts3_porter.c a651e287e02b49b565a6ccf9441959d434489156
|
||||
F ext/fts3/fts3_snippet.c 6c2eb6d872d66b2a9aa5663f2662e993f18a6496
|
||||
F ext/fts3/fts3_tokenizer.c 3dc76eaea6b58ecfbe50135b8473aa668d712dcd
|
||||
F ext/fts3/fts3_tokenizer.h 7ff73caa3327589bf6550f60d93ebdd1f6a0fb5c
|
||||
F ext/fts3/fts3_tokenizer1.c 11a604a53cff5e8c28882727bf794e5252e5227b
|
||||
F ext/fts3/fts3_write.c c7d549ac5a2733d1d3004a784ad8387f5c65fc75
|
||||
F ext/fts3/fts3_write.c ee50b8feb757bf0cddc522223ebd49f91985a1ad
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/icu/README.txt 3b130aa66e7a681136f6add198b076a2f90d1e33
|
||||
F ext/icu/icu.c 12e763d288d23b5a49de37caa30737b971a2f1e2
|
||||
@ -380,7 +377,7 @@ F test/fts2q.test b2fbbe038b7a31a52a6079b215e71226d8c6a682
|
||||
F test/fts2r.test b154c30b63061d8725e320fba1a39e2201cadd5e
|
||||
F test/fts2token.test d8070b241a15ff13592a9ae4a8b7c171af6f445a
|
||||
F test/fts3.test ae0433b09b12def08105640e57693726c4949338
|
||||
F test/fts3_common.tcl 8f75c15fa4507d923a1c21152e2716d77dc74661
|
||||
F test/fts3_common.tcl 363b6b215cb88ad9a59c5fd7c9d4dd0581446497
|
||||
F test/fts3aa.test 5327d4c1d9b6c61021696746cc9a6cdc5bf159c0
|
||||
F test/fts3ab.test 09aeaa162aee6513d9ff336b6932211008b9d1f9
|
||||
F test/fts3ac.test 356280144a2c92aa7b11474afadfe62a437fcd69
|
||||
@ -405,7 +402,7 @@ F test/fts3expr.test 05dab77387801e4900009917bb18f556037d82da
|
||||
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
|
||||
F test/fts3malloc.test d02ee86b21edd2b43044e0d6dfdcd26cb6efddcb
|
||||
F test/fts3near.test dc196dd17b4606f440c580d45b3d23aa975fd077
|
||||
F test/fts3rnd.test 44fa7209327deabc3ca22e2ff7a293b0bd46c37f
|
||||
F test/fts3rnd.test d7fe25493aa76f5010df0a6dbfa4dfa14f537c26
|
||||
F test/func.test af106ed834001738246d276659406823e35cde7b
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
F test/fuzz.test a4174c3009a3e2c2e14b31b364ebf7ddb49de2c9
|
||||
@ -781,14 +778,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
P 54b955c36ba5c139a63c6031855305b764d3fa6c
|
||||
R af7bd7d961d62f8a3ad909680a657a87
|
||||
U drh
|
||||
Z 29173053da939d420a44ec000f9044f8
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (GNU/Linux)
|
||||
|
||||
iD8DBQFLIEwtoxKgR168RlERArN7AJwJu6zTK/fKFR2tbMFA0GU+gGv4YACffJG4
|
||||
rSGfNuCvvW2w3AtoGqVeahA=
|
||||
=A3lG
|
||||
-----END PGP SIGNATURE-----
|
||||
P ee9b1c05a7f12d3d668b804bd11ae0def984b66e
|
||||
R 58b4a041207a70975c8de2329badf743
|
||||
U dan
|
||||
Z 97d832b78b48585e6dc269202723d83a
|
||||
|
@ -1 +1 @@
|
||||
ee9b1c05a7f12d3d668b804bd11ae0def984b66e
|
||||
48c0db0eb2d134bb302bb5eca6beb0ec46736257
|
@ -325,19 +325,21 @@ proc doPassiveTest {name sql catchres} {
|
||||
set modes [list 100000 transient 1 persistent]
|
||||
} else {
|
||||
set answers [list $catchres]
|
||||
set modes [list 0 nofail]
|
||||
set modes [list 0 ""]
|
||||
}
|
||||
set str [join $answers " OR "]
|
||||
|
||||
foreach {nRepeat zName} $modes {
|
||||
for {set iFail 1} 1 {incr iFail} {
|
||||
for {set iFail 48} 1 {incr iFail} {
|
||||
if {$::DO_MALLOC_TEST} {sqlite3_memdebug_fail $iFail -repeat $nRepeat}
|
||||
|
||||
set res [uplevel [list catchsql $sql]]
|
||||
if {[lsearch -exact $answers $res]>=0} {
|
||||
set res $str
|
||||
}
|
||||
do_test $name.$zName.$iFail [list set {} $res] $str
|
||||
set testname "$name.$zName.$iFail"
|
||||
if {$zName == ""} { set testname $name }
|
||||
do_test $testname [list set {} $res] $str
|
||||
set nFail [sqlite3_memdebug_fail -1 -benigncnt nBenign]
|
||||
if {$nFail==0} break
|
||||
}
|
||||
|
@ -20,6 +20,9 @@ source $testdir/fts3_common.tcl
|
||||
set nVocab 100
|
||||
set lVocab [list]
|
||||
|
||||
expr srand(0)
|
||||
|
||||
|
||||
# Generate a vocabulary of nVocab words. Each word is 3 characters long.
|
||||
#
|
||||
set lChar {a b c d e f g h i j k l m n o p q r s t u v w x y z}
|
||||
@ -149,6 +152,7 @@ foreach nodesize {50 500 1000 2000} {
|
||||
}
|
||||
|
||||
for {set iTest 0} {$iTest <= 100} {incr iTest} {
|
||||
catchsql COMMIT
|
||||
|
||||
set DO_MALLOC_TEST 0
|
||||
set nRep 10
|
||||
@ -170,11 +174,11 @@ foreach nodesize {50 500 1000 2000} {
|
||||
while {[info exists ::t1($iInsert)]} {
|
||||
set iInsert [expr {int(rand()*1000000)}]
|
||||
}
|
||||
db transaction {
|
||||
execsql BEGIN
|
||||
insert_row $iInsert
|
||||
update_row $iUpdate
|
||||
delete_row $iDelete
|
||||
}
|
||||
if {0==($iTest%2)} { execsql COMMIT }
|
||||
|
||||
# Pick 10 terms from the vocabulary. Check that the results of querying
|
||||
# the database for the set of documents containing each of these terms
|
||||
@ -293,6 +297,8 @@ foreach nodesize {50 500 1000 2000} {
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
catchsql COMMIT
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user