Have NEAR queries use incremental merging. Fix issues surrounding the deferred token optimization.

FossilOrigin-Name: 9d10a6846b12a9cc8fd4fdc3affd931a27218b5a
This commit is contained in:
dan
2011-06-07 18:35:45 +00:00
parent ebcdc73f53
commit 3eabcf5f46
5 changed files with 320 additions and 84 deletions
+292 -71
View File
@@ -1069,7 +1069,6 @@ static int fts3InitVtab(
p->nPendingData = 0;
p->azColumn = (char **)&p[1];
p->pTokenizer = pTokenizer;
p->nNodeSize = 1000;
p->nMaxPendingData = FTS3_MAX_PENDING_DATA;
p->bHasDocsize = (isFts4 && bNoDocsize==0);
p->bHasStat = isFts4;
@@ -1127,6 +1126,7 @@ static int fts3InitVtab(
** function sqlite3Fts3SegReaderCost() for details).
*/
fts3DatabasePageSize(&rc, p);
p->nNodeSize = p->nPgsz-35;
/* Declare the table schema to SQLite. */
fts3DeclareVtab(&rc, p);
@@ -1862,7 +1862,19 @@ static int fts3PoslistPhraseMerge(
}
/*
** Merge two position-lists as required by the NEAR operator.
** Merge two position-lists as required by the NEAR operator. The argument
** position lists correspond to the left and right phrases of an expression
** like:
**
** "phrase 1" NEAR "phrase number 2"
**
** Position list *pp1 corresponds to the left-hand side of the NEAR
** expression and *pp2 to the right. As usual, the indexes in the position
** lists are the offsets of the last token in each phrase (tokens "1" and "2"
** in the example above).
**
** The output position list - written to *pp - is a copy of *pp2 with those
** entries that are not sufficiently NEAR entries in *pp1 removed.
*/
static int fts3PoslistNearMerge(
char **pp, /* Output buffer */
@@ -1875,34 +1887,27 @@ static int fts3PoslistNearMerge(
char *p1 = *pp1;
char *p2 = *pp2;
if( !pp ){
if( fts3PoslistPhraseMerge(0, nRight, 0, 0, pp1, pp2) ) return 1;
*pp1 = p1;
*pp2 = p2;
return fts3PoslistPhraseMerge(0, nLeft, 0, 0, pp2, pp1);
char *pTmp1 = aTmp;
char *pTmp2;
char *aTmp2;
int res = 1;
fts3PoslistPhraseMerge(&pTmp1, nRight, 0, 0, pp1, pp2);
aTmp2 = pTmp2 = pTmp1;
*pp1 = p1;
*pp2 = p2;
fts3PoslistPhraseMerge(&pTmp2, nLeft, 1, 0, pp2, pp1);
if( pTmp1!=aTmp && pTmp2!=aTmp2 ){
fts3PoslistMerge(pp, &aTmp, &aTmp2);
}else if( pTmp1!=aTmp ){
fts3PoslistCopy(pp, &aTmp);
}else if( pTmp2!=aTmp2 ){
fts3PoslistCopy(pp, &aTmp2);
}else{
char *pTmp1 = aTmp;
char *pTmp2;
char *aTmp2;
int res = 1;
fts3PoslistPhraseMerge(&pTmp1, nRight, 0, 0, pp1, pp2);
aTmp2 = pTmp2 = pTmp1;
*pp1 = p1;
*pp2 = p2;
fts3PoslistPhraseMerge(&pTmp2, nLeft, 1, 0, pp2, pp1);
if( pTmp1!=aTmp && pTmp2!=aTmp2 ){
fts3PoslistMerge(pp, &aTmp, &aTmp2);
}else if( pTmp1!=aTmp ){
fts3PoslistCopy(pp, &aTmp);
}else if( pTmp2!=aTmp2 ){
fts3PoslistCopy(pp, &aTmp2);
}else{
res = 0;
}
return res;
res = 0;
}
return res;
}
/*
@@ -3244,6 +3249,7 @@ static void fts3EvalAllocateReaders(
Fts3Cursor *pCsr,
Fts3Expr *pExpr,
int *pnToken, /* OUT: Total number of tokens in phrase. */
int *pnOr, /* OUT: Total number of OR nodes in expr. */
int *pRc
){
if( pExpr && SQLITE_OK==*pRc ){
@@ -3262,8 +3268,9 @@ static void fts3EvalAllocateReaders(
}
}
}else{
fts3EvalAllocateReaders(pCsr, pExpr->pLeft, pnToken, pRc);
fts3EvalAllocateReaders(pCsr, pExpr->pRight, pnToken, pRc);
*pnOr += (pExpr->eType==FTSQUERY_OR);
fts3EvalAllocateReaders(pCsr, pExpr->pLeft, pnToken, pnOr, pRc);
fts3EvalAllocateReaders(pCsr, pExpr->pRight, pnToken, pnOr, pRc);
}
}
}
@@ -3545,6 +3552,7 @@ static int fts3EvalPhraseNext(
if( p->bIncr ){
assert( p->nToken==1 );
assert( pDL->pNextDocid==0 );
rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
&pDL->iDocid, &pDL->pList, &pDL->nList
);
@@ -3602,9 +3610,6 @@ static void fts3EvalStartReaders(
pExpr->bDeferred = (i==nToken);
*pRc = fts3EvalPhraseStart(pCsr, bOptOk, pExpr->pPhrase);
}else{
if( pExpr->eType==FTSQUERY_NEAR ){
bOptOk = 0;
}
fts3EvalStartReaders(pCsr, pExpr->pLeft, bOptOk, pRc);
fts3EvalStartReaders(pCsr, pExpr->pRight, bOptOk, pRc);
pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
@@ -3700,14 +3705,17 @@ static void fts3EvalNearTrim(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
typedef struct Fts3TokenAndCost Fts3TokenAndCost;
struct Fts3TokenAndCost {
Fts3PhraseToken *pToken;
Fts3Expr *pRoot;
int nOvfl;
int iCol;
};
static void fts3EvalTokenCosts(
Fts3Cursor *pCsr,
Fts3Expr *pRoot,
Fts3Expr *pExpr,
Fts3TokenAndCost **ppTC,
Fts3Expr ***ppOr,
int *pRc
){
if( *pRc==SQLITE_OK && pExpr ){
@@ -3716,13 +3724,19 @@ static void fts3EvalTokenCosts(
int i;
for(i=0; *pRc==SQLITE_OK && i<pPhrase->nToken; i++){
Fts3TokenAndCost *pTC = (*ppTC)++;
pTC->pRoot = pRoot;
pTC->pToken = &pPhrase->aToken[i];
pTC->iCol = pPhrase->iColumn;
*pRc = sqlite3Fts3MsrOvfl(pCsr, pTC->pToken->pSegcsr, &pTC->nOvfl);
}
}else if( pExpr->eType==FTSQUERY_AND ){
fts3EvalTokenCosts(pCsr, pExpr->pLeft, ppTC, pRc);
fts3EvalTokenCosts(pCsr, pExpr->pRight, ppTC, pRc);
}else if( pExpr->eType!=FTSQUERY_NOT ){
if( pExpr->eType==FTSQUERY_OR ){
pRoot = pExpr;
**ppOr = pExpr;
(*ppOr)++;
}
fts3EvalTokenCosts(pCsr, pRoot, pExpr->pLeft, ppTC, ppOr, pRc);
fts3EvalTokenCosts(pCsr, pRoot, pExpr->pRight, ppTC, ppOr, pRc);
}
}
}
@@ -3773,13 +3787,87 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
return SQLITE_OK;
}
static int fts3EvalSelectDeferred(
Fts3Cursor *pCsr,
Fts3Expr *pRoot,
Fts3TokenAndCost *aTC,
int nTC
){
int nDocSize = 0;
int nDocEst = 0;
int rc = SQLITE_OK;
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
int ii;
int nOvfl = 0;
int nTerm = 0;
for(ii=0; ii<nTC; ii++){
if( aTC[ii].pRoot==pRoot ){
nOvfl += aTC[ii].nOvfl;
nTerm++;
}
}
if( nOvfl==0 || nTerm<2 ) return SQLITE_OK;
rc = fts3EvalAverageDocsize(pCsr, &nDocSize);
for(ii=0; ii<nTerm && rc==SQLITE_OK; ii++){
int jj;
Fts3TokenAndCost *pTC = 0;
for(jj=0; jj<nTC; jj++){
if( aTC[jj].pToken && aTC[jj].pRoot==pRoot
&& (!pTC || aTC[jj].nOvfl<pTC->nOvfl)
){
pTC = &aTC[jj];
}
}
assert( pTC );
/* At this point pTC points to the cheapest remaining token. */
if( ii==0 ){
if( pTC->nOvfl ){
nDocEst = (pTC->nOvfl * pTab->nPgsz + pTab->nPgsz) / 10;
}else{
/* TODO: Fix this so that the doclist need not be read twice. */
Fts3PhraseToken *pToken = pTC->pToken;
int nList = 0;
char *pList = 0;
rc = fts3TermSelect(pTab, pToken, pTC->iCol, 1, &nList, &pList);
if( rc==SQLITE_OK ){
nDocEst = fts3DoclistCountDocids(1, pList, nList);
}
sqlite3_free(pList);
if( rc==SQLITE_OK ){
rc = sqlite3Fts3TermSegReaderCursor(pCsr,
pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
);
}
}
}else{
if( pTC->nOvfl>=(nDocEst*nDocSize) ){
Fts3PhraseToken *pToken = pTC->pToken;
rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol);
fts3SegReaderCursorFree(pToken->pSegcsr);
pToken->pSegcsr = 0;
}
nDocEst = 1 + (nDocEst/4);
}
pTC->pToken = 0;
}
return rc;
}
int sqlite3Fts3EvalStart(Fts3Cursor *pCsr, Fts3Expr *pExpr, int bOptOk){
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
int rc = SQLITE_OK;
int nToken = 0;
int nOr = 0;
/* Allocate a MultiSegReader for each token in the expression. */
fts3EvalAllocateReaders(pCsr, pExpr, &nToken, &rc);
fts3EvalAllocateReaders(pCsr, pExpr, &nToken, &nOr, &rc);
/* Call fts3EvalPhraseStart() on all phrases in the expression. TODO:
** This call will eventually also be responsible for determining which
@@ -3799,23 +3887,35 @@ int sqlite3Fts3EvalStart(Fts3Cursor *pCsr, Fts3Expr *pExpr, int bOptOk){
** call. This is known as a "deferred" token.
*/
/* If bOptOk is true, check if there are any tokens that can be
** deferred (strategy 3). */
/* If bOptOk is true, check if there are any tokens that should be deferred.
*/
if( rc==SQLITE_OK && bOptOk && nToken>1 && pTab->bHasStat ){
Fts3TokenAndCost *aTC;
aTC = (Fts3TokenAndCost *)sqlite3_malloc(sizeof(Fts3TokenAndCost) * nToken);
Fts3Expr **apOr;
aTC = (Fts3TokenAndCost *)sqlite3_malloc(
sizeof(Fts3TokenAndCost) * nToken
+ sizeof(Fts3Expr *) * nOr
);
apOr = (Fts3Expr **)&aTC[nToken];
if( !aTC ){
rc = SQLITE_NOMEM;
}else{
int ii;
int nDocEst = 0;
int nDocSize;
Fts3TokenAndCost *pTC = aTC;
Fts3Expr **ppOr = apOr;
rc = fts3EvalAverageDocsize(pCsr, &nDocSize);
fts3EvalTokenCosts(pCsr, pExpr, &pTC, &rc);
fts3EvalTokenCosts(pCsr, 0, pExpr, &pTC, &ppOr, &rc);
nToken = pTC-aTC;
nOr = ppOr-apOr;
rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken);
for(ii=0; rc==SQLITE_OK && ii<nOr; ii++){
rc = fts3EvalSelectDeferred(pCsr, apOr[ii], aTC, nToken);
}
#if 0
for(ii=0; rc==SQLITE_OK && ii<nToken; ii++){
int jj;
pTC = 0;
@@ -3826,6 +3926,7 @@ int sqlite3Fts3EvalStart(Fts3Cursor *pCsr, Fts3Expr *pExpr, int bOptOk){
}
assert( pTC );
/* At this point pTC points to the cheapest remaining token. */
if( ii==0 ){
if( pTC->nOvfl ){
@@ -3857,15 +3958,13 @@ int sqlite3Fts3EvalStart(Fts3Cursor *pCsr, Fts3Expr *pExpr, int bOptOk){
}
pTC->pToken = 0;
}
#endif
sqlite3_free(aTC);
}
}
fts3EvalStartReaders(pCsr, pExpr, bOptOk, &rc);
/* Fix the results of NEAR expressions. */
fts3EvalNearTrim(pCsr, pExpr, &rc);
return rc;
}
@@ -3878,6 +3977,98 @@ static void fts3EvalFreeDeferredDoclist(Fts3Phrase *pPhrase){
}
}
static int fts3EvalNearTrim2(
int nNear,
char *aTmp, /* Temporary space to use */
char **paPoslist, /* IN/OUT: Position list */
int *pnToken, /* IN/OUT: Tokens in phrase of *paPoslist */
Fts3Phrase *pPhrase /* The phrase object to trim the doclist of */
){
int nParam1 = nNear + pPhrase->nToken;
int nParam2 = nNear + *pnToken;
char *p2;
char *pOut;
int res;
p2 = pOut = pPhrase->doclist.pList;
res = fts3PoslistNearMerge(
&pOut, aTmp, nParam1, nParam2, paPoslist, &p2
);
pPhrase->doclist.nList = pOut - pPhrase->doclist.pList;
*paPoslist = pPhrase->doclist.pList;
*pnToken = pPhrase->nToken;
return res;
}
static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
int res = 1;
/* The following block runs if pExpr is the root of a NEAR query.
** For example, the query:
**
** "w" NEAR "x" NEAR "y" NEAR "z"
**
** which is represented in tree form as:
**
** |
** +--NEAR--+ <-- root of NEAR query
** | |
** +--NEAR--+ "z"
** | |
** +--NEAR--+ "y"
** | |
** "w" "x"
**
** The right-hand child of a NEAR node is always a phrase. The
** left-hand child may be either a phrase or a NEAR node. There are
** no exceptions to this.
*/
if( *pRc==SQLITE_OK
&& pExpr->eType==FTSQUERY_NEAR
&& pExpr->bEof==0
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
){
Fts3Expr *p;
int nTmp = 0; /* Bytes of temp space */
char *aTmp; /* Temp space for PoslistNearMerge() */
/* Allocate temporary working space. */
for(p=pExpr; p->pLeft; p=p->pLeft){
nTmp += p->pRight->pPhrase->doclist.nList;
}
nTmp += p->pPhrase->doclist.nList;
aTmp = sqlite3_malloc(nTmp*2);
if( !aTmp ){
*pRc = SQLITE_NOMEM;
res = 0;
}else{
char *aPoslist = p->pPhrase->doclist.pList;
int nToken = p->pPhrase->nToken;
for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
Fts3Phrase *pPhrase = p->pRight->pPhrase;
int nNear = p->nNear;
res = fts3EvalNearTrim2(nNear, aTmp, &aPoslist, &nToken, pPhrase);
}
aPoslist = pExpr->pRight->pPhrase->doclist.pList;
nToken = pExpr->pRight->pPhrase->nToken;
for(p=pExpr->pLeft; p && res; p=p->pLeft){
int nNear = p->pParent->nNear;
Fts3Phrase *pPhrase = (
p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
);
res = fts3EvalNearTrim2(nNear, aTmp, &aPoslist, &nToken, pPhrase);
}
}
sqlite3_free(aTmp);
}
return res;
}
/*
** This macro is used by the fts3EvalNext() function. The two arguments are
** 64-bit docid values. If the current query is "ORDER BY docid ASC", then
@@ -3901,7 +4092,6 @@ static void fts3EvalNext(
case FTSQUERY_AND: {
Fts3Expr *pLeft = pExpr->pLeft;
Fts3Expr *pRight = pExpr->pRight;
assert( !pLeft->bDeferred || !pRight->bDeferred );
if( pLeft->bDeferred ){
fts3EvalNext(pCsr, pRight, pRc);
@@ -3924,7 +4114,7 @@ static void fts3EvalNext(
fts3EvalNext(pCsr, pRight, pRc);
}
}
pExpr->iDocid = pLeft->iDocid;
pExpr->bEof = (pLeft->bEof || pRight->bEof);
}
@@ -3987,12 +4177,6 @@ static void fts3EvalNext(
fts3EvalFreeDeferredDoclist(pPhrase);
*pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof);
pExpr->iDocid = pPhrase->doclist.iDocid;
#if 0
printf("token \"%.*s\" docid=%lld\n",
pPhrase->aToken[0].n, pPhrase->aToken[0].z, pExpr->iDocid
);
#endif
break;
}
}
@@ -4000,7 +4184,7 @@ static void fts3EvalNext(
}
static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
int bHit = 0;
int bHit = 1;
if( *pRc==SQLITE_OK ){
switch( pExpr->eType ){
case FTSQUERY_NEAR:
@@ -4008,15 +4192,40 @@ static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
bHit = (
fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
&& fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
&& fts3EvalNearTest(pExpr, pRc)
);
/* If this is a NEAR node and the NEAR expression does not match
** any rows, zero the doclist for all phrases involved in the NEAR.
** This is because the snippet(), offsets() and matchinfo() functions
** are not supposed to recognize any instances of phrases that are
** part of unmatched NEAR queries. For example if this expression:
**
** ... MATCH 'a OR (b NEAR c)'
**
** is matched against a row containing:
**
** 'a b d e'
**
** then any snippet() should ony highlight the "a" term, not the "b"
** (as "b" is part of a non-matching NEAR clause).
*/
if( pExpr->eType==FTSQUERY_NEAR && bHit==0 ){
Fts3Expr *p;
for(p=pExpr; p->pPhrase==0; p=p->pLeft){
p->pRight->pPhrase->doclist.pList = 0;
}
p->pPhrase->doclist.pList = 0;
}
break;
case FTSQUERY_OR:
bHit = (
fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc)
|| fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc)
);
case FTSQUERY_OR: {
int bHit1 = fts3EvalDeferredTest(pCsr, pExpr->pLeft, pRc);
int bHit2 = fts3EvalDeferredTest(pCsr, pExpr->pRight, pRc);
bHit = bHit1 || bHit2;
break;
}
case FTSQUERY_NOT:
bHit = (
@@ -4026,11 +4235,15 @@ static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
break;
default: {
Fts3Phrase *pPhrase = pExpr->pPhrase;
fts3EvalFreeDeferredDoclist(pPhrase);
*pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
bHit = (pPhrase->doclist.pList!=0);
pExpr->iDocid = pCsr->iPrevId;
if( pCsr->pDeferred ){
Fts3Phrase *pPhrase = pExpr->pPhrase;
fts3EvalFreeDeferredDoclist(pPhrase);
*pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
bHit = (pPhrase->doclist.pList!=0);
pExpr->iDocid = pCsr->iPrevId;
}else{
bHit = (pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId);
}
break;
}
}
@@ -4052,11 +4265,12 @@ static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
static int fts3EvalLoadDeferred(Fts3Cursor *pCsr, int *pRc){
int rc = *pRc;
int bMiss = 0;
if( rc==SQLITE_OK && pCsr->pDeferred ){
rc = fts3CursorSeek(0, pCsr);
if( rc==SQLITE_OK ){
sqlite3Fts3FreeDeferredDoclists(pCsr);
rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
if( rc==SQLITE_OK ){
if( pCsr->pDeferred ){
rc = fts3CursorSeek(0, pCsr);
if( rc==SQLITE_OK ){
rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
}
}
bMiss = (0==fts3EvalDeferredTest(pCsr, pCsr->pExpr, &rc));
sqlite3Fts3FreeDeferredDoclists(pCsr);
@@ -4151,6 +4365,13 @@ int sqlite3Fts3EvalPhraseDoclist(
}
}
if( rc==SQLITE_OK
&& pExpr->pParent
&& pExpr->pParent->eType==FTSQUERY_NEAR
){
}
*pnList = pPhrase->doclist.nAll;
*ppList = pPhrase->doclist.aAll;
return rc;
+9 -9
View File
@@ -1,5 +1,5 @@
C Merge\sthe\slatest\strunk\schanges\sinto\sthe\sfts3-prefix-search\sbranch.
D 2011-06-06T18:14:25.721
C Have\sNEAR\squeries\suse\sincremental\smerging.\sFix\sissues\ssurrounding\sthe\sdeferred\stoken\soptimization.
D 2011-06-07T18:35:45.780
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 11dcc00a8d0e5202def00e81732784fb0cc4fe1d
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -61,7 +61,7 @@ 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 d0970d9fa0a63ac470007ac5e14645f5b874b70f
F ext/fts3/fts3.c 9d2d2cab4d64f0769046d88b6740c6e1f229d1e3
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h d76b021d5b7061eff7aa4055b5938eebef2bdb6a
F ext/fts3/fts3_aux.c baed9dab7fb4604ae8cafdb2d7700abe93beffbe
@@ -464,14 +464,14 @@ F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
F test/fts3d.test 95fb3c862cbc4297c93fceb9a635543744e9ef52
F test/fts3defer.test 7c8a38d5f617d7b52ae1c43ed73c536e7e895a35
F test/fts3defer2.test 288bef6de15557319b8c12d476ebdc83688ef96c
F test/fts3defer2.test ad5bd3ae616fb719eb06b0a73eb5c8fb1c411989
F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
F test/fts3expr.test 5e745b2b6348499d9ef8d59015de3182072c564c
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
F test/fts3fault.test f83e556465bb69dc8bc676339eca408dce4ca246
F test/fts3fault2.test dc96203af6ba31ce20163fc35460e1556e8edf4d
F test/fts3malloc.test 9c8cc3f885bb4dfc66d0460c52f68f45e4710d1b
F test/fts3matchinfo.test cc0b009edbbf575283d5fdb53271179e0d8019ba
F test/fts3matchinfo.test f424597b6843659ecbc2009e8823380233ebf375
F test/fts3near.test 2e318ee434d32babd27c167142e2b94ddbab4844
F test/fts3prefix.test 36246609111ec1683f7ea5ed27666ce2cefb5676
F test/fts3query.test ef79d31fdb355d094baec1c1b24b60439a1fb8a2
@@ -943,7 +943,7 @@ F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
F tool/symbols.sh bc2a3709940d47c8ac8e0a1fdf17ec801f015a00
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
F tool/warnings.sh 347d974d143cf132f953b565fbc03026f19fcb4d
P 89f2f482e077241ac29a58eadf44a72a9c01f98c 98ccfa930e8e5f10808a518e3e22e85e8a8a65c2
R b612d83743a894702aacbc42c433c9e9
U drh
Z c6414e08a953b76b4b33ed29bc763b72
P 567dd84359218245d4e6887547e2a48881f2c8e0
R 020efe4a51ef4472e0e5c3f4175d0de6
U dan
Z 740d1ddba83232619fca71041707ab60
+1 -1
View File
@@ -1 +1 @@
567dd84359218245d4e6887547e2a48881f2c8e0
9d10a6846b12a9cc8fd4fdc3affd931a27218b5a
+14 -3
View File
@@ -48,17 +48,22 @@ do_execsql_test 1.1.4 {
UPDATE t1_segments SET block = zeroblob(length(block)) WHERE length(block)>10000;
} {2}
do_execsql_test 1.2.0 {
SELECT content FROM t1 WHERE t1 MATCH 'f (e a)';
} {{a b c d e f a x y}}
do_execsql_test 1.2.1 {
SELECT content FROM t1 WHERE t1 MATCH 'f (e NEAR/2 a)';
} {{a b c d e f a x y}}
breakpoint
do_execsql_test 1.2.2 {
SELECT snippet(t1, '[', ']'), offsets(t1), mit(matchinfo(t1, 'pcxnal'))
FROM t1 WHERE t1 MATCH 'f (e NEAR/2 a)';
} [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 8 8 1 8 8 8 5001 9]
[list 3 1 1 1 1 1 1 1 1 8 8 8 5001 9]
]
do_execsql_test 1.2.3 {
@@ -67,7 +72,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 8 8 2 8 8 8 5001 9]
[list 3 1 1 1 1 1 1 1 2 8 8 8 5001 9]
]
do_execsql_test 1.3.1 { DROP TABLE t1 }
@@ -99,8 +104,14 @@ foreach {tn sql} {
[list 2 1 1 54 54 1 3 3 54 372 7] \
]
set sqlite_fts3_enable_parentheses 1
do_execsql_test 2.2.$tn.2 {
SELECT mit(matchinfo(t2, 'x')) FROM t2 WHERE t2 MATCH 'g z';
} [list \
[list 1 2 2 1 54 54] \
]
set sqlite_fts3_enable_parentheses 1
do_execsql_test 2.2.$tn.3 {
SELECT mit(matchinfo(t2, 'x')) FROM t2 WHERE t2 MATCH 'g OR (g z)';
} [list \
[list 1 2 2 1 2 2 1 54 54] \
+4
View File
@@ -68,7 +68,11 @@ do_execsql_test 3.1 {
do_execsql_test 3.2 {
CREATE VIRTUAL TABLE xx USING FTS4;
}
do_execsql_test 3.3 {
SELECT * FROM xx WHERE xx MATCH 'abc';
}
do_execsql_test 3.4 {
SELECT * FROM xx WHERE xx MATCH 'a b c';
}