Fixes for the matchinfo() function related to FTS4 common token handling.
FossilOrigin-Name: deb80eac9112d21835dfd3cee08ed8f09d975bf7
This commit is contained in:
parent
cfff8343ae
commit
378d0ab97b
@ -2108,7 +2108,6 @@ static int fts3DeferExpression(Fts3Cursor *pCsr, Fts3Expr *pExpr){
|
||||
if( pExpr->eType==FTSQUERY_PHRASE ){
|
||||
int iCol = pExpr->pPhrase->iColumn;
|
||||
int i;
|
||||
pExpr->bDeferred = 1;
|
||||
for(i=0; rc==SQLITE_OK && i<pExpr->pPhrase->nToken; i++){
|
||||
Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
|
||||
if( pToken->pDeferred==0 ){
|
||||
@ -2170,22 +2169,28 @@ static int fts3PhraseSelect(
|
||||
int iCol = pPhrase->iColumn;
|
||||
int isTermPos = (pPhrase->nToken>1 || isReqPos);
|
||||
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
|
||||
int isFirst = 1;
|
||||
|
||||
int iPrevTok = 0;
|
||||
int nDoc = 0;
|
||||
|
||||
/* If this is an xFilter() evaluation, create a segment-reader for each
|
||||
** phrase token. Or, if this is an xNest() or snippet/offsets/matchinfo
|
||||
** phrase token. Or, if this is an xNext() or snippet/offsets/matchinfo
|
||||
** evaluation, only create segment-readers if there are no Fts3DeferredToken
|
||||
** objects attached to the phrase-tokens.
|
||||
*/
|
||||
for(ii=0; ii<pPhrase->nToken; ii++){
|
||||
Fts3PhraseToken *pTok = &pPhrase->aToken[ii];
|
||||
if( pTok->pArray==0 && (pCsr->doDeferred==0 || pTok->pDeferred==0) ){
|
||||
rc = fts3TermSegReaderArray(
|
||||
pCsr, pTok->z, pTok->n, pTok->isPrefix, &pTok->pArray
|
||||
);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
if( pTok->pArray==0 ){
|
||||
if( (pCsr->eEvalmode==FTS3_EVAL_FILTER)
|
||||
|| (pCsr->eEvalmode==FTS3_EVAL_NEXT && pCsr->pDeferred==0)
|
||||
|| (pCsr->eEvalmode==FTS3_EVAL_MATCHINFO && pTok->bFulltext)
|
||||
){
|
||||
rc = fts3TermSegReaderArray(
|
||||
pCsr, pTok->z, pTok->n, pTok->isPrefix, &pTok->pArray
|
||||
);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2199,7 +2204,12 @@ static int fts3PhraseSelect(
|
||||
** are processed in order from least to most costly. Otherwise, tokens
|
||||
** are processed in the order in which they occur in the phrase.
|
||||
*/
|
||||
if( pCsr->doDeferred || isReqPos ){
|
||||
if( pCsr->eEvalmode==FTS3_EVAL_MATCHINFO ){
|
||||
assert( isReqPos );
|
||||
iTok = ii;
|
||||
pTok = &pPhrase->aToken[iTok];
|
||||
if( pTok->bFulltext==0 ) continue;
|
||||
}else if( pCsr->eEvalmode==FTS3_EVAL_NEXT || isReqPos ){
|
||||
iTok = ii;
|
||||
pTok = &pPhrase->aToken[iTok];
|
||||
}else{
|
||||
@ -2227,21 +2237,23 @@ static int fts3PhraseSelect(
|
||||
}
|
||||
}
|
||||
|
||||
if( pCsr->doDeferred && pTok->pDeferred ){
|
||||
if( pCsr->eEvalmode==FTS3_EVAL_NEXT && pTok->pDeferred ){
|
||||
rc = fts3DeferredTermSelect(pTok->pDeferred, isTermPos, &nList, &pList);
|
||||
}else{
|
||||
assert( pTok->pArray );
|
||||
rc = fts3TermSelect(p, pTok, iCol, isTermPos, &nList, &pList);
|
||||
pTok->bFulltext = 1;
|
||||
}
|
||||
assert( rc!=SQLITE_OK || pCsr->doDeferred || pTok->pArray==0 );
|
||||
assert( rc!=SQLITE_OK || pCsr->eEvalmode || pTok->pArray==0 );
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
|
||||
if( ii==0 ){
|
||||
if( isFirst ){
|
||||
pOut = pList;
|
||||
nOut = nList;
|
||||
if( pCsr->doDeferred==0 && pPhrase->nToken>1 ){
|
||||
if( pCsr->eEvalmode==FTS3_EVAL_FILTER && pPhrase->nToken>1 ){
|
||||
nDoc = fts3DoclistCountDocids(1, pOut, nOut);
|
||||
}
|
||||
isFirst = 0;
|
||||
}else{
|
||||
/* Merge the new term list and the current output. */
|
||||
char *aLeft, *aRight;
|
||||
@ -2282,8 +2294,8 @@ static int fts3PhraseSelect(
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
if( ii!=pPhrase->nToken ){
|
||||
assert( pCsr->doDeferred==0 && isReqPos==0 );
|
||||
if( ii!=pPhrase->nToken && pCsr->eEvalmode==FTS3_EVAL_FILTER ){
|
||||
assert( pCsr->eEvalmode==FTS3_EVAL_FILTER && isReqPos==0 );
|
||||
fts3DoclistStripPositions(pOut, &nOut);
|
||||
}
|
||||
*paOut = pOut;
|
||||
@ -2398,7 +2410,8 @@ static int fts3ExprAllocateSegReaders(
|
||||
){
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
|
||||
if( pCsr->doDeferred ) return SQLITE_OK;
|
||||
assert( pCsr->eEvalmode!=FTS3_EVAL_MATCHINFO );
|
||||
if( pCsr->eEvalmode==FTS3_EVAL_NEXT ) return SQLITE_OK;
|
||||
if( pnExpr && pExpr->eType!=FTSQUERY_AND ){
|
||||
(*pnExpr)++;
|
||||
pnExpr = 0;
|
||||
@ -2559,7 +2572,7 @@ static int fts3EvalExpr(
|
||||
paOut, pnOut
|
||||
);
|
||||
fts3ExprFreeSegReaders(pExpr);
|
||||
}else if( p->doDeferred==0 && pExpr->eType==FTSQUERY_AND ){
|
||||
}else if( p->eEvalmode==FTS3_EVAL_FILTER && pExpr->eType==FTSQUERY_AND ){
|
||||
ExprAndCost *aExpr = 0; /* Array of AND'd expressions and costs */
|
||||
int nExpr = 0; /* Size of aExpr[] */
|
||||
char *aRet = 0; /* Doclist to return to caller */
|
||||
@ -2628,7 +2641,7 @@ static int fts3EvalExpr(
|
||||
assert( pExpr->eType==FTSQUERY_NEAR
|
||||
|| pExpr->eType==FTSQUERY_OR
|
||||
|| pExpr->eType==FTSQUERY_NOT
|
||||
|| (pExpr->eType==FTSQUERY_AND && p->doDeferred)
|
||||
|| (pExpr->eType==FTSQUERY_AND && p->eEvalmode==FTS3_EVAL_NEXT)
|
||||
);
|
||||
|
||||
if( 0==(rc = fts3EvalExpr(p, pExpr->pRight, &aRight, &nRight, isReqPos))
|
||||
@ -2725,9 +2738,7 @@ static int fts3EvalDeferred(
|
||||
if( rc==SQLITE_OK ){
|
||||
char *a = 0;
|
||||
int n = 0;
|
||||
pCsr->doDeferred = 1;
|
||||
rc = fts3EvalExpr(pCsr, pCsr->pExpr, &a, &n, 0);
|
||||
pCsr->doDeferred = 0;
|
||||
assert( n>=0 );
|
||||
*pbRes = (n>0);
|
||||
sqlite3_free(a);
|
||||
@ -2752,6 +2763,7 @@ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
|
||||
|
||||
pCsr->eEvalmode = FTS3_EVAL_NEXT;
|
||||
do {
|
||||
if( pCsr->aDoclist==0 ){
|
||||
if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){
|
||||
@ -3003,9 +3015,24 @@ static int fts3RollbackMethod(sqlite3_vtab *pVtab){
|
||||
*/
|
||||
int sqlite3Fts3ExprLoadDoclist(Fts3Cursor *pCsr, Fts3Expr *pExpr){
|
||||
int rc;
|
||||
pCsr->doDeferred = 1;
|
||||
assert( pExpr->eType==FTSQUERY_PHRASE && pExpr->pPhrase );
|
||||
assert( pCsr->eEvalmode==FTS3_EVAL_NEXT );
|
||||
rc = fts3EvalExpr(pCsr, pExpr, &pExpr->aDoclist, &pExpr->nDoclist, 1);
|
||||
pCsr->doDeferred = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int sqlite3Fts3ExprLoadFtDoclist(
|
||||
Fts3Cursor *pCsr,
|
||||
Fts3Expr *pExpr,
|
||||
char **paDoclist,
|
||||
int *pnDoclist
|
||||
){
|
||||
int rc;
|
||||
assert( pCsr->eEvalmode==FTS3_EVAL_NEXT );
|
||||
assert( pExpr->eType==FTSQUERY_PHRASE && pExpr->pPhrase );
|
||||
pCsr->eEvalmode = FTS3_EVAL_MATCHINFO;
|
||||
rc = fts3EvalExpr(pCsr, pExpr, paDoclist, pnDoclist, 1);
|
||||
pCsr->eEvalmode = FTS3_EVAL_NEXT;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -163,10 +163,14 @@ struct Fts3Cursor {
|
||||
int nDoclist; /* Size of buffer at aDoclist */
|
||||
int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
|
||||
u32 *aMatchinfo; /* Information about most recent match */
|
||||
int doDeferred;
|
||||
int eEvalmode; /* An FTS3_EVAL_XX constant */
|
||||
int nRowAvg; /* Average size of database rows, in pages */
|
||||
};
|
||||
|
||||
#define FTS3_EVAL_FILTER 0
|
||||
#define FTS3_EVAL_NEXT 1
|
||||
#define FTS3_EVAL_MATCHINFO 2
|
||||
|
||||
/*
|
||||
** The Fts3Cursor.eSearch member is always set to one of the following.
|
||||
** Actualy, Fts3Cursor.eSearch can be greater than or equal to
|
||||
@ -191,16 +195,24 @@ struct Fts3Cursor {
|
||||
** sequence. A single token is the base case and the most common case.
|
||||
** For a sequence of tokens contained in double-quotes (i.e. "one two three")
|
||||
** nToken will be the number of tokens in the string.
|
||||
**
|
||||
** The nDocMatch and nMatch variables contain data that may be used by the
|
||||
** matchinfo() function. They are populated when the full-text index is
|
||||
** queried for hits on the phrase. If one or more tokens in the phrase
|
||||
** are deferred, the nDocMatch and nMatch variables are populated based
|
||||
** on the assumption that the
|
||||
*/
|
||||
struct Fts3PhraseToken {
|
||||
char *z; /* Text of the token */
|
||||
int n; /* Number of bytes in buffer z */
|
||||
int isPrefix; /* True if token ends with a "*" character */
|
||||
int bFulltext; /* True if full-text index was used */
|
||||
Fts3SegReaderArray *pArray; /* Segment-reader for this token */
|
||||
Fts3DeferredToken *pDeferred; /* Deferred token object for this token */
|
||||
};
|
||||
|
||||
struct Fts3Phrase {
|
||||
/* Variables populated by fts3_expr.c when parsing a MATCH expression */
|
||||
int nToken; /* Number of tokens in the phrase */
|
||||
int iColumn; /* Index of column this phrase must match */
|
||||
int isNot; /* Phrase prefixed by unary not (-) operator */
|
||||
@ -228,8 +240,6 @@ struct Fts3Expr {
|
||||
Fts3Expr *pRight; /* Right operand */
|
||||
Fts3Phrase *pPhrase; /* Valid if eType==FTSQUERY_PHRASE */
|
||||
|
||||
int bDeferred;
|
||||
|
||||
int isLoaded; /* True if aDoclist/nDoclist are initialized. */
|
||||
char *aDoclist; /* Buffer containing doclist */
|
||||
int nDoclist; /* Size of aDoclist in bytes */
|
||||
@ -307,6 +317,7 @@ void sqlite3Fts3Dequote(char *);
|
||||
|
||||
char *sqlite3Fts3FindPositions(Fts3Expr *, sqlite3_int64, int);
|
||||
int sqlite3Fts3ExprLoadDoclist(Fts3Cursor *, Fts3Expr *);
|
||||
int sqlite3Fts3ExprLoadFtDoclist(Fts3Cursor *, Fts3Expr *, char **, int *);
|
||||
int sqlite3Fts3ExprNearTrim(Fts3Expr *, Fts3Expr *, int);
|
||||
|
||||
/* fts3_tokenizer.c */
|
||||
|
@ -106,6 +106,18 @@ static int fts3isspace(char c){
|
||||
return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate nByte bytes of memory using sqlite3_malloc(). If successful,
|
||||
** zero the memory before returning a pointer to it. If unsuccessful,
|
||||
** return NULL.
|
||||
*/
|
||||
static void *fts3MallocZero(int nByte){
|
||||
void *pRet = sqlite3_malloc(nByte);
|
||||
if( pRet ) memset(pRet, 0, nByte);
|
||||
return pRet;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Extract the next token from buffer z (length n) using the tokenizer
|
||||
** and other information (column names etc.) in pParse. Create an Fts3Expr
|
||||
@ -143,11 +155,10 @@ static int getNextToken(
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
|
||||
pRet = (Fts3Expr *)sqlite3_malloc(nByte);
|
||||
pRet = (Fts3Expr *)fts3MallocZero(nByte);
|
||||
if( !pRet ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
memset(pRet, 0, nByte);
|
||||
pRet->eType = FTSQUERY_PHRASE;
|
||||
pRet->pPhrase = (Fts3Phrase *)&pRet[1];
|
||||
pRet->pPhrase->nToken = 1;
|
||||
@ -233,10 +244,9 @@ static int getNextString(
|
||||
p->pPhrase = (Fts3Phrase *)&p[1];
|
||||
}
|
||||
p->pPhrase = (Fts3Phrase *)&p[1];
|
||||
memset(&p->pPhrase->aToken[ii], 0, sizeof(Fts3PhraseToken));
|
||||
p->pPhrase->nToken = ii+1;
|
||||
p->pPhrase->aToken[ii].n = nToken;
|
||||
p->pPhrase->aToken[ii].pDeferred = 0;
|
||||
p->pPhrase->aToken[ii].pArray = 0;
|
||||
memcpy(&zTemp[nTemp], zToken, nToken);
|
||||
nTemp += nToken;
|
||||
if( iEnd<nInput && zInput[iEnd]=='*' ){
|
||||
@ -374,11 +384,10 @@ static int getNextNode(
|
||||
if( fts3isspace(cNext)
|
||||
|| cNext=='"' || cNext=='(' || cNext==')' || cNext==0
|
||||
){
|
||||
pRet = (Fts3Expr *)sqlite3_malloc(sizeof(Fts3Expr));
|
||||
pRet = (Fts3Expr *)fts3MallocZero(sizeof(Fts3Expr));
|
||||
if( !pRet ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
memset(pRet, 0, sizeof(Fts3Expr));
|
||||
pRet->eType = pKey->eType;
|
||||
pRet->nNear = nNear;
|
||||
*ppExpr = pRet;
|
||||
@ -554,13 +563,12 @@ static int fts3ExprParse(
|
||||
&& p->eType==FTSQUERY_PHRASE && p->pPhrase->isNot
|
||||
){
|
||||
/* Create an implicit NOT operator. */
|
||||
Fts3Expr *pNot = sqlite3_malloc(sizeof(Fts3Expr));
|
||||
Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
|
||||
if( !pNot ){
|
||||
sqlite3Fts3ExprFree(p);
|
||||
rc = SQLITE_NOMEM;
|
||||
goto exprparse_out;
|
||||
}
|
||||
memset(pNot, 0, sizeof(Fts3Expr));
|
||||
pNot->eType = FTSQUERY_NOT;
|
||||
pNot->pRight = p;
|
||||
if( pNotBranch ){
|
||||
@ -588,13 +596,12 @@ static int fts3ExprParse(
|
||||
/* Insert an implicit AND operator. */
|
||||
Fts3Expr *pAnd;
|
||||
assert( pRet && pPrev );
|
||||
pAnd = sqlite3_malloc(sizeof(Fts3Expr));
|
||||
pAnd = fts3MallocZero(sizeof(Fts3Expr));
|
||||
if( !pAnd ){
|
||||
sqlite3Fts3ExprFree(p);
|
||||
rc = SQLITE_NOMEM;
|
||||
goto exprparse_out;
|
||||
}
|
||||
memset(pAnd, 0, sizeof(Fts3Expr));
|
||||
pAnd->eType = FTSQUERY_AND;
|
||||
insertBinaryOperator(&pRet, pPrev, pAnd);
|
||||
pPrev = pAnd;
|
||||
|
@ -268,7 +268,6 @@ static int fts3ExprLoadDoclists(
|
||||
}
|
||||
if( pnPhrase ) *pnPhrase = sCtx.nPhrase;
|
||||
if( pnToken ) *pnToken = sCtx.nToken;
|
||||
sqlite3Fts3SegmentsClose((Fts3Table *)pCsr->base.pVtab);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -793,20 +792,47 @@ static int fts3ExprGlobalMatchinfoCb(
|
||||
void *pCtx /* Pointer to MatchInfo structure */
|
||||
){
|
||||
MatchInfo *p = (MatchInfo *)pCtx;
|
||||
char *pCsr;
|
||||
Fts3Cursor *pCsr = p->pCursor;
|
||||
char *pIter;
|
||||
char *pEnd;
|
||||
char *pFree = 0;
|
||||
const int iStart = 2 + (iPhrase * p->nCol * 3) + 1;
|
||||
|
||||
assert( pExpr->isLoaded );
|
||||
assert( pExpr->eType==FTSQUERY_PHRASE );
|
||||
|
||||
/* Fill in the global hit count matrix row for this phrase. */
|
||||
pCsr = pExpr->aDoclist;
|
||||
pEnd = &pExpr->aDoclist[pExpr->nDoclist];
|
||||
while( pCsr<pEnd ){
|
||||
while( *pCsr++ & 0x80 ); /* Skip past docid. */
|
||||
fts3LoadColumnlistCounts(&pCsr, &p->aMatchinfo[iStart], 1);
|
||||
if( pCsr->pDeferred ){
|
||||
Fts3Phrase *pPhrase = pExpr->pPhrase;
|
||||
int ii;
|
||||
for(ii=0; ii<pPhrase->nToken; ii++){
|
||||
if( pPhrase->aToken[ii].bFulltext ) break;
|
||||
}
|
||||
if( ii<pPhrase->nToken ){
|
||||
int nFree = 0;
|
||||
int rc = sqlite3Fts3ExprLoadFtDoclist(pCsr, pExpr, &pFree, &nFree);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
pIter = pFree;
|
||||
pEnd = &pFree[nFree];
|
||||
}else{
|
||||
int nDoc = p->aMatchinfo[2 + 3*p->nCol*p->aMatchinfo[0]];
|
||||
for(ii=0; ii<p->nCol; ii++){
|
||||
p->aMatchinfo[iStart + ii*3] = nDoc;
|
||||
p->aMatchinfo[iStart + ii*3 + 1] = nDoc;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}else{
|
||||
pIter = pExpr->aDoclist;
|
||||
pEnd = &pExpr->aDoclist[pExpr->nDoclist];
|
||||
}
|
||||
|
||||
/* Fill in the global hit count matrix row for this phrase. */
|
||||
while( pIter<pEnd ){
|
||||
while( *pIter++ & 0x80 ); /* Skip past docid. */
|
||||
fts3LoadColumnlistCounts(&pIter, &p->aMatchinfo[iStart], 1);
|
||||
}
|
||||
|
||||
sqlite3_free(pFree);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@ -875,15 +901,14 @@ static int fts3GetMatchinfo(Fts3Cursor *pCsr){
|
||||
}
|
||||
memset(sInfo.aMatchinfo, 0, sizeof(u32)*nMatchinfo);
|
||||
|
||||
|
||||
/* First element of match-info is the number of phrases in the query */
|
||||
sInfo.aMatchinfo[0] = nPhrase;
|
||||
sInfo.aMatchinfo[1] = sInfo.nCol;
|
||||
(void)fts3ExprIterate(pCsr->pExpr, fts3ExprGlobalMatchinfoCb,(void*)&sInfo);
|
||||
if( pTab->bHasDocsize ){
|
||||
int ofst = 2 + 3*sInfo.aMatchinfo[0]*sInfo.aMatchinfo[1];
|
||||
rc = sqlite3Fts3MatchinfoDocsizeGlobal(pCsr, &sInfo.aMatchinfo[ofst]);
|
||||
}
|
||||
(void)fts3ExprIterate(pCsr->pExpr, fts3ExprGlobalMatchinfoCb,(void*)&sInfo);
|
||||
pCsr->aMatchinfo = sInfo.aMatchinfo;
|
||||
pCsr->isMatchinfoNeeded = 1;
|
||||
}
|
||||
@ -993,6 +1018,7 @@ void sqlite3Fts3Snippet(
|
||||
}
|
||||
|
||||
snippet_out:
|
||||
sqlite3Fts3SegmentsClose(pTab);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_result_error_code(pCtx, rc);
|
||||
sqlite3_free(res.z);
|
||||
@ -1172,6 +1198,7 @@ void sqlite3Fts3Offsets(
|
||||
offsets_out:
|
||||
sqlite3_free(sCtx.aTerm);
|
||||
assert( rc!=SQLITE_DONE );
|
||||
sqlite3Fts3SegmentsClose(pTab);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_result_error_code(pCtx, rc);
|
||||
sqlite3_free(res.z);
|
||||
@ -1191,6 +1218,7 @@ void sqlite3Fts3Matchinfo(sqlite3_context *pContext, Fts3Cursor *pCsr){
|
||||
return;
|
||||
}
|
||||
rc = fts3GetMatchinfo(pCsr);
|
||||
sqlite3Fts3SegmentsClose((Fts3Table *)pCsr->base.pVtab );
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_result_error_code(pContext, rc);
|
||||
}else{
|
||||
|
@ -2644,7 +2644,7 @@ static void fts3DeferredDoclistClear(Fts3Expr *pExpr){
|
||||
if( pExpr ){
|
||||
fts3DeferredDoclistClear(pExpr->pLeft);
|
||||
fts3DeferredDoclistClear(pExpr->pRight);
|
||||
if( pExpr->bDeferred && pExpr->isLoaded ){
|
||||
if( pExpr->isLoaded ){
|
||||
sqlite3_free(pExpr->aDoclist);
|
||||
pExpr->isLoaded = 0;
|
||||
pExpr->aDoclist = 0;
|
||||
@ -2665,7 +2665,9 @@ void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *pCsr){
|
||||
sqlite3_free(pDef->pList);
|
||||
pDef->pList = 0;
|
||||
}
|
||||
fts3DeferredDoclistClear(pCsr->pExpr);
|
||||
if( pCsr->pDeferred ){
|
||||
fts3DeferredDoclistClear(pCsr->pExpr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
22
manifest
22
manifest
@ -1,5 +1,5 @@
|
||||
C Add\snew\stest\sfile\sfts3defer2.test.
|
||||
D 2010-10-22T19:03:34
|
||||
C Fixes\sfor\sthe\smatchinfo()\sfunction\srelated\sto\sFTS4\scommon\stoken\shandling.
|
||||
D 2010-10-23T19:07:30
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 2c8cefd962eca0147132c7cf9eaa4bb24c656f3f
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -61,19 +61,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 e2f031ea6b213371a31cc5bf181c2177fef86aad
|
||||
F ext/fts3/fts3.c b7442369abecdda3cb58dc0ed482e7d1e852028f
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h 068d80157cc7a4bf674d2df817f3b427001ad94a
|
||||
F ext/fts3/fts3_expr.c a5aee50edde20e5c9116199bd58be869a3a22c9f
|
||||
F ext/fts3/fts3Int.h 11fa12ce041bacbc6ac53db127eb0bcc0538af51
|
||||
F ext/fts3/fts3_expr.c ee48b9278b8b2432a05a03320fbcacba151dbaa5
|
||||
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 8df6f6efcc4e9e31f8bf73a4007c2e9abca1dfba
|
||||
F ext/fts3/fts3_snippet.c ca60a2a47de5e7abb22a804ccd1a743f81c2fe3e
|
||||
F ext/fts3/fts3_snippet.c 300c12b7f0a2a6ae0491bb2d00e2d5ff9c28f685
|
||||
F ext/fts3/fts3_tokenizer.c b4f2d01c24573852755bc92864816785dae39318
|
||||
F ext/fts3/fts3_tokenizer.h 13ffd9fcb397fec32a05ef5cd9e0fa659bf3dbd3
|
||||
F ext/fts3/fts3_tokenizer1.c 6e5cbaa588924ac578263a598e4fb9f5c9bb179d
|
||||
F ext/fts3/fts3_write.c 54ddeed7323f62af6e55162f0d4102822b991684
|
||||
F ext/fts3/fts3_write.c 1b9211904f8157ebca8e17034e1150f3653e6c3f
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/icu/README.txt bf8461d8cdc6b8f514c080e4e10dc3b2bbdfefa9
|
||||
@ -434,7 +434,7 @@ F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
|
||||
F test/fts3cov.test 54cf1f98c72abee246447cd688590898c9ecbaf7
|
||||
F test/fts3d.test 95fb3c862cbc4297c93fceb9a635543744e9ef52
|
||||
F test/fts3defer.test cf66bf69afcc2fb8373d3aed31c55399409e83f2
|
||||
F test/fts3defer2.test 98259e5d7fa16b2d275d9b6a6c0c972e285fa18c
|
||||
F test/fts3defer2.test acd2fdd4db0a3b7f0ce6b1b3154c9521cb62d27d
|
||||
F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
|
||||
F test/fts3expr.test 5e745b2b6348499d9ef8d59015de3182072c564c
|
||||
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
|
||||
@ -876,7 +876,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
P 1c9c70fec3c88319f7b2efe5316694a6ce0ab1a5
|
||||
R d4195a622cd830429b9e32aeb4872a48
|
||||
P 5a4d5bfcaeb78a81713f138b01c0ea45a15c4d6c
|
||||
R eb3b2e3c665e63f01c554e4a5a259aeb
|
||||
U dan
|
||||
Z 7c9af859e7e36df7363e90eaf6cd38eb
|
||||
Z f37bf8cb2dd9e3f74310b44a4142ec1c
|
||||
|
@ -1 +1 @@
|
||||
5a4d5bfcaeb78a81713f138b01c0ea45a15c4d6c
|
||||
deb80eac9112d21835dfd3cee08ed8f09d975bf7
|
@ -57,7 +57,7 @@ do_execsql_test 1.2.2 {
|
||||
} [list \
|
||||
{a b c d [e] [f] [a] x y} \
|
||||
{0 1 8 1 0 0 10 1 0 2 12 1} \
|
||||
[list 3 1 1 1 1 1 1 1 1 1 1 3 13336 9]
|
||||
[list 3 1 1 1 1 1 3 3 1 3 3 3 13336 9]
|
||||
]
|
||||
|
||||
do_execsql_test 1.2.3 {
|
||||
@ -66,7 +66,7 @@ do_execsql_test 1.2.3 {
|
||||
} [list \
|
||||
{[a] b c d [e] [f] [a] x y} \
|
||||
{0 2 0 1 0 1 8 1 0 0 10 1 0 2 12 1} \
|
||||
[list 3 1 1 1 1 1 1 1 2 2 1 3 13336 9]
|
||||
[list 3 1 1 1 1 1 3 3 2 3 3 3 13336 9]
|
||||
]
|
||||
|
||||
do_execsql_test 1.3.1 { DROP TABLE t1 }
|
||||
@ -77,9 +77,10 @@ do_execsql_test 1.3.1 { DROP TABLE t1 }
|
||||
do_execsql_test 2.1.1 {
|
||||
CREATE VIRTUAL TABLE t2 USING fts4;
|
||||
}
|
||||
do_execsql_test 2.1.2 "INSERT INTO t2 VALUES('[string repeat {a } 20000]')"
|
||||
do_execsql_test 2.1.3 "INSERT INTO t2 VALUES('[string repeat {z } 20000]')"
|
||||
do_execsql_test 2.1.4 {
|
||||
do_execsql_test 2.1.2 "INSERT INTO t2 VALUES('[string repeat {a } 10000]')"
|
||||
do_execsql_test 2.1.3 "INSERT INTO t2 VALUES('b [string repeat {z } 10000]')"
|
||||
do_execsql_test 2.1.4 [string repeat "INSERT INTO t2 VALUES('x');" 50]
|
||||
do_execsql_test 2.1.5 {
|
||||
INSERT INTO t2 VALUES('a b c d e f g');
|
||||
INSERT INTO t2 VALUES('a b c d e f g');
|
||||
}
|
||||
@ -91,13 +92,12 @@ foreach {tn sql} {
|
||||
WHERE length(block)>10000;
|
||||
}
|
||||
} {
|
||||
if {$tn==3} break
|
||||
execsql $sql
|
||||
do_execsql_test 2.2.$tn.1 {
|
||||
SELECT mit(matchinfo(t2)) FROM t2 WHERE t2 MATCH 'a b';
|
||||
} [list \
|
||||
[list 2 1 1 20002 3 1 2 2 4 10004 7] \
|
||||
[list 2 1 1 20002 3 1 2 2 4 10004 7] \
|
||||
[list 2 1 1 54 54 1 3 3 54 372 7] \
|
||||
[list 2 1 1 54 54 1 3 3 54 372 7] \
|
||||
]
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user