Index: ext/fts5/fts5_expr.c ================================================================== --- ext/fts5/fts5_expr.c +++ ext/fts5/fts5_expr.c @@ -744,52 +744,65 @@ /* ** Initialize all term iterators in the pNear object. If any term is found ** to match no documents at all, return immediately without initializing any ** further iterators. +** +** If an error occurs, return an SQLite error code. Otherwise, return +** SQLITE_OK. It is not considered an error if some term matches zero +** documents. */ static int fts5ExprNearInitAll( Fts5Expr *pExpr, Fts5ExprNode *pNode ){ Fts5ExprNearset *pNear = pNode->pNear; - int i, j; - int rc = SQLITE_OK; - int bEof = 1; + int i; assert( pNode->bNomatch==0 ); - for(i=0; rc==SQLITE_OK && inPhrase; i++){ + for(i=0; inPhrase; i++){ Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; - for(j=0; jnTerm; j++){ - Fts5ExprTerm *pTerm = &pPhrase->aTerm[j]; - Fts5ExprTerm *p; - - for(p=pTerm; p && rc==SQLITE_OK; p=p->pSynonym){ - if( p->pIter ){ - sqlite3Fts5IterClose(p->pIter); - p->pIter = 0; - } - rc = sqlite3Fts5IndexQuery( - pExpr->pIndex, p->zTerm, (int)strlen(p->zTerm), - (pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) | - (pExpr->bDesc ? FTS5INDEX_QUERY_DESC : 0), - pNear->pColset, - &p->pIter - ); - assert( rc==SQLITE_OK || p->pIter==0 ); - if( p->pIter && 0==sqlite3Fts5IterEof(p->pIter) ){ - bEof = 0; - } - } - - if( bEof ) break; - } - if( bEof ) break; - } - - pNode->bEof = bEof; - return rc; + if( pPhrase->nTerm==0 ){ + pNode->bEof = 1; + return SQLITE_OK; + }else{ + int j; + for(j=0; jnTerm; j++){ + Fts5ExprTerm *pTerm = &pPhrase->aTerm[j]; + Fts5ExprTerm *p; + int bHit = 0; + + for(p=pTerm; p; p=p->pSynonym){ + int rc; + if( p->pIter ){ + sqlite3Fts5IterClose(p->pIter); + p->pIter = 0; + } + rc = sqlite3Fts5IndexQuery( + pExpr->pIndex, p->zTerm, (int)strlen(p->zTerm), + (pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) | + (pExpr->bDesc ? FTS5INDEX_QUERY_DESC : 0), + pNear->pColset, + &p->pIter + ); + assert( (rc==SQLITE_OK)==(p->pIter!=0) ); + if( rc!=SQLITE_OK ) return rc; + if( 0==sqlite3Fts5IterEof(p->pIter) ){ + bHit = 1; + } + } + + if( bHit==0 ){ + pNode->bEof = 1; + return SQLITE_OK; + } + } + } + } + + pNode->bEof = 0; + return SQLITE_OK; } /* ** If pExpr is an ASC iterator, this function returns a value with the ** same sign as: Index: ext/fts5/test/fts5prefix.test ================================================================== --- ext/fts5/test/fts5prefix.test +++ ext/fts5/test/fts5prefix.test @@ -7,11 +7,11 @@ # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # -# This file containst tests focused on prefix indexes. +# This file contains tests focused on prefix indexes. # source [file join [file dirname [info script]] fts5_common.tcl] set testprefix fts5prefix Index: ext/fts5/test/fts5simple2.test ================================================================== --- ext/fts5/test/fts5simple2.test +++ ext/fts5/test/fts5simple2.test @@ -329,10 +329,45 @@ INSERT INTO t2(rowid, x) VALUES(1000, 'a b c'); COMMIT; UPDATE t2 SET x=x; DELETE FROM t2; } + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 17.0 { + CREATE VIRTUAL TABLE t2 USING fts5(x, y); + BEGIN; + INSERT INTO t2 VALUES('a aa aaa', 'b bb bbb'); + INSERT INTO t2 VALUES('a aa aaa', 'b bb bbb'); + INSERT INTO t2 VALUES('a aa aaa', 'b bb bbb'); + COMMIT; +} +do_execsql_test 17.1 { SELECT * FROM t2('y:a*') WHERE rowid BETWEEN 10 AND 20 } +do_execsql_test 17.2 { + BEGIN; + INSERT INTO t2 VALUES('a aa aaa', 'b bb bbb'); + SELECT * FROM t2('y:a*') WHERE rowid BETWEEN 10 AND 20 ; +} +do_execsql_test 17.3 { + COMMIT +} + +reset_db +do_execsql_test 17.4 { + CREATE VIRTUAL TABLE t2 USING fts5(x, y); + BEGIN; + INSERT INTO t2 VALUES('a aa aaa', 'b bb bbb'); + INSERT INTO t2 VALUES('a aa aaa', 'b bb bbb'); + SELECT * FROM t2('y:a*') WHERE rowid>66; +} +do_execsql_test 17.5 { SELECT * FROM t2('x:b* OR y:a*') } +do_execsql_test 17.5 { COMMIT ; SELECT * FROM t2('x:b* OR y:a*') } +do_execsql_test 17.6 { + SELECT * FROM t2('x:b* OR y:a*') WHERE rowid>55 +} #db eval {SELECT rowid, fts5_decode_none(rowid, block) aS r FROM t2_data} {puts $r} finish_test