mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Improve performance of fts5 queries.
FossilOrigin-Name: 2334e88244afe6387208be5d527aba9b5ddf4e4c
This commit is contained in:
@ -62,6 +62,9 @@ struct Fts5ExprNode {
|
||||
int bEof; /* True at EOF */
|
||||
int bNomatch; /* True if entry is not a match */
|
||||
|
||||
/* Next method for this node. */
|
||||
int (*xNext)(Fts5Expr*, Fts5ExprNode*, int, i64);
|
||||
|
||||
i64 iRowid; /* Current rowid */
|
||||
Fts5ExprNearset *pNear; /* For FTS5_STRING - cluster of phrases */
|
||||
|
||||
@ -73,6 +76,12 @@ struct Fts5ExprNode {
|
||||
|
||||
#define Fts5NodeIsString(p) ((p)->eType==FTS5_TERM || (p)->eType==FTS5_STRING)
|
||||
|
||||
/*
|
||||
** Invoke the xNext method of an Fts5ExprNode object. This macro should be
|
||||
** used as if it has the same signature as the xNext() methods themselves.
|
||||
*/
|
||||
#define fts5ExprNodeNext(a,b,c,d) (b)->xNext((a), (b), (c), (d))
|
||||
|
||||
/*
|
||||
** An instance of the following structure represents a single search term
|
||||
** or term prefix.
|
||||
@ -234,7 +243,15 @@ int sqlite3Fts5ExprNew(
|
||||
sParse.rc = SQLITE_NOMEM;
|
||||
sqlite3Fts5ParseNodeFree(sParse.pExpr);
|
||||
}else{
|
||||
pNew->pRoot = sParse.pExpr;
|
||||
if( !sParse.pExpr ){
|
||||
const int nByte = sizeof(Fts5ExprNode);
|
||||
pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&sParse.rc, nByte);
|
||||
if( pNew->pRoot ){
|
||||
pNew->pRoot->bEof = 1;
|
||||
}
|
||||
}else{
|
||||
pNew->pRoot = sParse.pExpr;
|
||||
}
|
||||
pNew->pIndex = 0;
|
||||
pNew->pConfig = pConfig;
|
||||
pNew->apExprPhrase = sParse.apPhrase;
|
||||
@ -500,12 +517,6 @@ static int fts5LookaheadReaderInit(
|
||||
return fts5LookaheadReaderNext(p);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int fts5LookaheadReaderEof(Fts5LookaheadReader *p){
|
||||
return (p->iPos==FTS5_LOOKAHEAD_EOF);
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct Fts5NearTrimmer Fts5NearTrimmer;
|
||||
struct Fts5NearTrimmer {
|
||||
Fts5LookaheadReader reader; /* Input iterator */
|
||||
@ -636,6 +647,7 @@ static int fts5ExprNearAdvanceFirst(
|
||||
Fts5ExprTerm *pTerm = &pNode->pNear->apPhrase[0]->aTerm[0];
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
pNode->bNomatch = 0;
|
||||
if( pTerm->pSynonym ){
|
||||
int bEof = 1;
|
||||
Fts5ExprTerm *p;
|
||||
@ -765,17 +777,6 @@ static int fts5ExprNearTest(
|
||||
for(pTerm=&pPhrase->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){
|
||||
Fts5IndexIter *pIter = pTerm->pIter;
|
||||
if( sqlite3Fts5IterEof(pIter)==0 ){
|
||||
#if 0
|
||||
int n;
|
||||
i64 iRowid;
|
||||
rc = sqlite3Fts5IterPoslist(pIter, pNear->pColset, 0, &n, &iRowid);
|
||||
if( rc!=SQLITE_OK ){
|
||||
*pRc = rc;
|
||||
return 0;
|
||||
}else if( iRowid==pNode->iRowid && n>0 ){
|
||||
pPhrase->poslist.n = 1;
|
||||
}
|
||||
#endif
|
||||
if( pIter->iRowid==pNode->iRowid && pIter->nData>0 ){
|
||||
pPhrase->poslist.n = 1;
|
||||
}
|
||||
@ -797,11 +798,6 @@ static int fts5ExprNearTest(
|
||||
}else{
|
||||
Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter;
|
||||
fts5BufferSet(&rc, &pPhrase->poslist, pIter->nData, pIter->pData);
|
||||
#if 0
|
||||
rc = sqlite3Fts5IterPoslistBuffer(
|
||||
pPhrase->aTerm[0].pIter, &pPhrase->poslist
|
||||
);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -888,6 +884,7 @@ static int fts5ExprNearNextMatch(
|
||||
if( iRowid==iLast ) continue;
|
||||
bMatch = 0;
|
||||
if( fts5ExprSynonymAdvanceto(pTerm, bDesc, &iLast, &rc) ){
|
||||
pNode->bNomatch = 0;
|
||||
pNode->bEof = 1;
|
||||
return rc;
|
||||
}
|
||||
@ -905,7 +902,8 @@ static int fts5ExprNearNextMatch(
|
||||
}while( bMatch==0 );
|
||||
|
||||
pNode->iRowid = iLast;
|
||||
pNode->bNomatch = (0==fts5ExprNearTest(&rc, pExpr, pNode));
|
||||
pNode->bNomatch = ((0==fts5ExprNearTest(&rc, pExpr, pNode)) && rc==SQLITE_OK);
|
||||
assert( pNode->bEof==0 || pNode->bNomatch==0 );
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -923,6 +921,7 @@ static int fts5ExprNearInitAll(
|
||||
int i, j;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
assert( pNode->bNomatch==0 );
|
||||
for(i=0; rc==SQLITE_OK && i<pNear->nPhrase; i++){
|
||||
Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
|
||||
for(j=0; j<pPhrase->nTerm; j++){
|
||||
@ -990,6 +989,7 @@ static int fts5RowidCmp(
|
||||
static void fts5ExprSetEof(Fts5ExprNode *pNode){
|
||||
int i;
|
||||
pNode->bEof = 1;
|
||||
pNode->bNomatch = 0;
|
||||
for(i=0; i<pNode->nChild; i++){
|
||||
fts5ExprSetEof(pNode->apChild[i]);
|
||||
}
|
||||
@ -1012,8 +1012,6 @@ static void fts5ExprNodeZeroPoslist(Fts5ExprNode *pNode){
|
||||
}
|
||||
|
||||
|
||||
static int fts5ExprNodeNext(Fts5Expr*, Fts5ExprNode*, int, i64);
|
||||
|
||||
/*
|
||||
** Argument pNode is an FTS5_AND node.
|
||||
*/
|
||||
@ -1093,6 +1091,33 @@ static int fts5NodeCompare(
|
||||
return fts5RowidCmp(pExpr, p1->iRowid, p2->iRowid);
|
||||
}
|
||||
|
||||
/*
|
||||
** xNext() method for a node of type FTS5_TERM.
|
||||
*/
|
||||
static int fts5ExprNodeNext_Term(
|
||||
Fts5Expr *pExpr,
|
||||
Fts5ExprNode *pNode,
|
||||
int bFromValid,
|
||||
i64 iFrom
|
||||
){
|
||||
int rc;
|
||||
Fts5IndexIter *pIter = pNode->pNear->apPhrase[0]->aTerm[0].pIter;
|
||||
|
||||
assert( pNode->bEof==0 );
|
||||
if( bFromValid ){
|
||||
rc = sqlite3Fts5IterNextFrom(pIter, iFrom);
|
||||
}else{
|
||||
rc = sqlite3Fts5IterNext(pIter);
|
||||
}
|
||||
if( rc==SQLITE_OK && sqlite3Fts5IterEof(pIter)==0 ){
|
||||
rc = fts5ExprTokenTest(pExpr, pNode);
|
||||
}else{
|
||||
pNode->bEof = 1;
|
||||
pNode->bNomatch = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Advance node iterator pNode, part of expression pExpr. If argument
|
||||
** bFromValid is zero, then pNode is advanced exactly once. Or, if argument
|
||||
@ -1100,7 +1125,7 @@ static int fts5NodeCompare(
|
||||
** rowid value iFrom. Whether "past" means "less than" or "greater than"
|
||||
** depends on whether this is an ASC or DESC iterator.
|
||||
*/
|
||||
static int fts5ExprNodeNext(
|
||||
static int fts5ExprNodeNext_Fallback(
|
||||
Fts5Expr *pExpr,
|
||||
Fts5ExprNode *pNode,
|
||||
int bFromValid,
|
||||
@ -1127,6 +1152,7 @@ static int fts5ExprNodeNext(
|
||||
rc = fts5ExprTokenTest(pExpr, pNode);
|
||||
}else{
|
||||
pNode->bEof = 1;
|
||||
pNode->bNomatch = 0;
|
||||
}
|
||||
return rc;
|
||||
};
|
||||
@ -1180,6 +1206,7 @@ static int fts5ExprNodeNext(
|
||||
|| pNode->iRowid==iFrom || pExpr->bDesc==(pNode->iRowid<iFrom) /* c */
|
||||
);
|
||||
|
||||
assert( pNode->bNomatch==0 || rc==SQLITE_OK );
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1246,6 +1273,7 @@ static int fts5ExprNodeNextMatch(
|
||||
rc = fts5ExprNodeNext(pExpr, p1, 0, 0);
|
||||
}
|
||||
pNode->bEof = p1->bEof;
|
||||
pNode->bNomatch = p1->bNomatch;
|
||||
pNode->iRowid = p1->iRowid;
|
||||
if( p1->bEof ){
|
||||
fts5ExprNodeZeroPoslist(p2);
|
||||
@ -1268,16 +1296,36 @@ static int fts5ExprNodeNextMatch(
|
||||
static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){
|
||||
int rc = SQLITE_OK;
|
||||
pNode->bEof = 0;
|
||||
pNode->bNomatch = 0;
|
||||
|
||||
if( Fts5NodeIsString(pNode) ){
|
||||
/* Initialize all term iterators in the NEAR object. */
|
||||
rc = fts5ExprNearInitAll(pExpr, pNode);
|
||||
}else{
|
||||
int i;
|
||||
int nEof = 0;
|
||||
for(i=0; i<pNode->nChild && rc==SQLITE_OK; i++){
|
||||
Fts5ExprNode *pChild = pNode->apChild[i];
|
||||
rc = fts5ExprNodeFirst(pExpr, pNode->apChild[i]);
|
||||
assert( pChild->bEof==0 || pChild->bEof==1 );
|
||||
nEof += pChild->bEof;
|
||||
}
|
||||
pNode->iRowid = pNode->apChild[0]->iRowid;
|
||||
|
||||
switch( pNode->eType ){
|
||||
case FTS5_AND:
|
||||
if( nEof>0 ) fts5ExprSetEof(pNode);
|
||||
break;
|
||||
|
||||
case FTS5_OR:
|
||||
if( pNode->nChild==nEof ) fts5ExprSetEof(pNode);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert( pNode->eType==FTS5_NOT );
|
||||
pNode->bEof = pNode->apChild[0]->bEof;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
@ -1305,7 +1353,7 @@ static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){
|
||||
int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){
|
||||
Fts5ExprNode *pRoot = p->pRoot;
|
||||
int rc = SQLITE_OK;
|
||||
if( pRoot ){
|
||||
if( pRoot->xNext ){
|
||||
p->pIndex = pIdx;
|
||||
p->bDesc = bDesc;
|
||||
rc = fts5ExprNodeFirst(p, pRoot);
|
||||
@ -1333,9 +1381,11 @@ int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){
|
||||
int sqlite3Fts5ExprNext(Fts5Expr *p, i64 iLast){
|
||||
int rc;
|
||||
Fts5ExprNode *pRoot = p->pRoot;
|
||||
assert( pRoot->bEof==0 && pRoot->bNomatch==0 );
|
||||
do {
|
||||
rc = fts5ExprNodeNext(p, pRoot, 0, 0);
|
||||
}while( pRoot->bNomatch && pRoot->bEof==0 && rc==SQLITE_OK );
|
||||
assert( pRoot->bNomatch==0 || (rc==SQLITE_OK && pRoot->bEof==0) );
|
||||
}while( pRoot->bNomatch );
|
||||
if( fts5RowidCmp(p, pRoot->iRowid, iLast)>0 ){
|
||||
pRoot->bEof = 1;
|
||||
}
|
||||
@ -1343,7 +1393,7 @@ int sqlite3Fts5ExprNext(Fts5Expr *p, i64 iLast){
|
||||
}
|
||||
|
||||
int sqlite3Fts5ExprEof(Fts5Expr *p){
|
||||
return (p->pRoot==0 || p->pRoot->bEof);
|
||||
return p->pRoot->bEof;
|
||||
}
|
||||
|
||||
i64 sqlite3Fts5ExprRowid(Fts5Expr *p){
|
||||
@ -1640,6 +1690,7 @@ int sqlite3Fts5ExprClonePhrase(
|
||||
pNew->apExprPhrase[0] = sCtx.pPhrase;
|
||||
pNew->pRoot->pNear->apPhrase[0] = sCtx.pPhrase;
|
||||
pNew->pRoot->pNear->nPhrase = 1;
|
||||
pNew->pRoot->xNext = fts5ExprNodeNext_Fallback;
|
||||
sCtx.pPhrase->pNode = pNew->pRoot;
|
||||
|
||||
if( pOrig->nTerm==1 && pOrig->aTerm[0].pSynonym==0 ){
|
||||
@ -1840,6 +1891,7 @@ Fts5ExprNode *sqlite3Fts5ParseNode(
|
||||
pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
|
||||
|
||||
if( pRet ){
|
||||
pRet->xNext = fts5ExprNodeNext_Fallback;
|
||||
pRet->eType = eType;
|
||||
pRet->pNear = pNear;
|
||||
if( eType==FTS5_STRING ){
|
||||
@ -1850,6 +1902,7 @@ Fts5ExprNode *sqlite3Fts5ParseNode(
|
||||
if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1 ){
|
||||
if( pNear->apPhrase[0]->aTerm[0].pSynonym==0 ){
|
||||
pRet->eType = FTS5_TERM;
|
||||
pRet->xNext = fts5ExprNodeNext_Term;
|
||||
}
|
||||
}else if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
|
||||
assert( pParse->rc==SQLITE_OK );
|
||||
@ -2144,7 +2197,7 @@ static void fts5ExprFunction(
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
char *zText;
|
||||
if( pExpr->pRoot==0 ){
|
||||
if( pExpr->pRoot->xNext==0 ){
|
||||
zText = sqlite3_mprintf("");
|
||||
}else if( bTcl ){
|
||||
zText = fts5ExprPrintTcl(pConfig, zNearsetCmd, pExpr->pRoot);
|
||||
|
Reference in New Issue
Block a user