mirror of
https://github.com/sqlite/sqlite.git
synced 2025-06-03 09:42:06 +03:00
Reimplement [ec69e09a] so that each call to the xNext() method does not involve two iterations of the match expression tree (only one).
FossilOrigin-Name: 80fe305b3eefb17310a9d6185d1c8cd73ee38b1e
This commit is contained in:
parent
5350d91ed3
commit
dbef6e752e
@ -48,10 +48,13 @@ struct Fts5Expr {
|
|||||||
** FTS5_OR (nChild, apChild valid)
|
** FTS5_OR (nChild, apChild valid)
|
||||||
** FTS5_NOT (nChild, apChild valid)
|
** FTS5_NOT (nChild, apChild valid)
|
||||||
** FTS5_STRING (pNear valid)
|
** FTS5_STRING (pNear valid)
|
||||||
|
** FTS5_TERM (pNear valid)
|
||||||
*/
|
*/
|
||||||
struct Fts5ExprNode {
|
struct Fts5ExprNode {
|
||||||
int eType; /* Node type */
|
int eType; /* Node type */
|
||||||
int bEof; /* True at EOF */
|
int bEof; /* True at EOF */
|
||||||
|
int bNomatch; /* True if entry is not a match */
|
||||||
|
|
||||||
i64 iRowid; /* Current rowid */
|
i64 iRowid; /* Current rowid */
|
||||||
Fts5ExprNearset *pNear; /* For FTS5_STRING - cluster of phrases */
|
Fts5ExprNearset *pNear; /* For FTS5_STRING - cluster of phrases */
|
||||||
|
|
||||||
@ -61,6 +64,8 @@ struct Fts5ExprNode {
|
|||||||
Fts5ExprNode *apChild[0]; /* Array of child nodes */
|
Fts5ExprNode *apChild[0]; /* Array of child nodes */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define Fts5NodeIsString(p) ((p)->eType==FTS5_TERM || (p)->eType==FTS5_STRING)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** An instance of the following structure represents a single search term
|
** An instance of the following structure represents a single search term
|
||||||
** or term prefix.
|
** or term prefix.
|
||||||
@ -287,7 +292,7 @@ int sqlite3Fts5ExprPhraseExpr(
|
|||||||
pNew->apExprPhrase = apPhrase;
|
pNew->apExprPhrase = apPhrase;
|
||||||
pNew->apExprPhrase[0] = pCopy;
|
pNew->apExprPhrase[0] = pCopy;
|
||||||
|
|
||||||
pNode->eType = FTS5_STRING;
|
pNode->eType = (pCopy->nTerm==1 ? FTS5_TERM : FTS5_STRING);
|
||||||
pNode->pNear = pNear;
|
pNode->pNear = pNear;
|
||||||
|
|
||||||
pNear->nPhrase = 1;
|
pNear->nPhrase = 1;
|
||||||
@ -590,13 +595,14 @@ static int fts5ExprNearIsMatch(int *pRc, Fts5ExprNearset *pNear){
|
|||||||
*/
|
*/
|
||||||
static int fts5ExprNearAdvanceFirst(
|
static int fts5ExprNearAdvanceFirst(
|
||||||
Fts5Expr *pExpr, /* Expression pPhrase belongs to */
|
Fts5Expr *pExpr, /* Expression pPhrase belongs to */
|
||||||
Fts5ExprNode *pNode, /* FTS5_STRING node */
|
Fts5ExprNode *pNode, /* FTS5_STRING or FTS5_TERM node */
|
||||||
int bFromValid,
|
int bFromValid,
|
||||||
i64 iFrom
|
i64 iFrom
|
||||||
){
|
){
|
||||||
Fts5IndexIter *pIter = pNode->pNear->apPhrase[0]->aTerm[0].pIter;
|
Fts5IndexIter *pIter = pNode->pNear->apPhrase[0]->aTerm[0].pIter;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
assert( Fts5NodeIsString(pNode) );
|
||||||
if( bFromValid ){
|
if( bFromValid ){
|
||||||
rc = sqlite3Fts5IterNextFrom(pIter, iFrom);
|
rc = sqlite3Fts5IterNextFrom(pIter, iFrom);
|
||||||
}else{
|
}else{
|
||||||
@ -642,55 +648,6 @@ static int fts5ExprAdvanceto(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
** All individual term iterators in pNear are guaranteed to be valid when
|
|
||||||
** this function is called. This function checks if all term iterators
|
|
||||||
** point to the same rowid, and if not, advances them until they do.
|
|
||||||
** If an EOF is reached before this happens, *pbEof is set to true before
|
|
||||||
** returning.
|
|
||||||
**
|
|
||||||
** SQLITE_OK is returned if an error occurs, or an SQLite error code
|
|
||||||
** otherwise. It is not considered an error code if an iterator reaches
|
|
||||||
** EOF.
|
|
||||||
*/
|
|
||||||
static int fts5ExprNearNextRowidMatch(
|
|
||||||
Fts5Expr *pExpr, /* Expression pPhrase belongs to */
|
|
||||||
Fts5ExprNode *pNode
|
|
||||||
){
|
|
||||||
Fts5ExprNearset *pNear = pNode->pNear;
|
|
||||||
i64 iLast; /* Lastest rowid any iterator points to */
|
|
||||||
int rc = SQLITE_OK;
|
|
||||||
|
|
||||||
/* Initialize iLast, the "lastest" rowid any iterator points to. If the
|
|
||||||
** iterator skips through rowids in the default ascending order, this means
|
|
||||||
** the maximum rowid. Or, if the iterator is "ORDER BY rowid DESC", then it
|
|
||||||
** means the minimum rowid. */
|
|
||||||
iLast = sqlite3Fts5IterRowid(pNear->apPhrase[0]->aTerm[0].pIter);
|
|
||||||
|
|
||||||
if( pNear->nPhrase>1 || pNear->apPhrase[0]->nTerm>1 ){
|
|
||||||
int i, j; /* Phrase and token index, respectively */
|
|
||||||
int bMatch; /* True if all terms are at the same rowid */
|
|
||||||
do {
|
|
||||||
bMatch = 1;
|
|
||||||
for(i=0; i<pNear->nPhrase; i++){
|
|
||||||
Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
|
|
||||||
for(j=0; j<pPhrase->nTerm; j++){
|
|
||||||
Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter;
|
|
||||||
i64 iRowid = sqlite3Fts5IterRowid(pIter);
|
|
||||||
if( iRowid!=iLast ) bMatch = 0;
|
|
||||||
if( fts5ExprAdvanceto(pIter, pExpr->bDesc, &iLast,&rc,&pNode->bEof) ){
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}while( bMatch==0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
pNode->iRowid = iLast;
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** IN/OUT parameter (*pa) points to a position list n bytes in size. If
|
** IN/OUT parameter (*pa) points to a position list n bytes in size. If
|
||||||
** the position list contains entries for column iCol, then (*pa) is set
|
** the position list contains entries for column iCol, then (*pa) is set
|
||||||
@ -817,45 +774,97 @@ static int fts5ExprNearTest(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int fts5ExprTokenTest(
|
||||||
|
Fts5Expr *pExpr, /* Expression that pNear is a part of */
|
||||||
|
Fts5ExprNode *pNode /* The "NEAR" node (FTS5_TERM) */
|
||||||
|
){
|
||||||
|
/* As this "NEAR" object is actually a single phrase that consists
|
||||||
|
** of a single term only, grab pointers into the poslist managed by the
|
||||||
|
** fts5_index.c iterator object. This is much faster than synthesizing
|
||||||
|
** a new poslist the way we have to for more complicated phrase or NEAR
|
||||||
|
** expressions. */
|
||||||
|
Fts5ExprNearset *pNear = pNode->pNear;
|
||||||
|
Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
|
||||||
|
Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter;
|
||||||
|
Fts5ExprColset *pColset = pNear->pColset;
|
||||||
|
const u8 *pPos;
|
||||||
|
int nPos;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
assert( pNode->eType==FTS5_TERM );
|
||||||
|
assert( pNear->nPhrase==1 && pPhrase->nTerm==1 );
|
||||||
|
|
||||||
|
rc = sqlite3Fts5IterPoslist(pIter, &pPos, &nPos, &pNode->iRowid);
|
||||||
|
|
||||||
|
/* If the term may match any column, then this must be a match.
|
||||||
|
** Return immediately in this case. Otherwise, try to find the
|
||||||
|
** part of the poslist that corresponds to the required column.
|
||||||
|
** If it can be found, return. If it cannot, the next iteration
|
||||||
|
** of the loop will test the next rowid in the database for this
|
||||||
|
** term. */
|
||||||
|
if( pColset==0 ){
|
||||||
|
assert( pPhrase->poslist.nSpace==0 );
|
||||||
|
pPhrase->poslist.p = (u8*)pPos;
|
||||||
|
pPhrase->poslist.n = nPos;
|
||||||
|
}else if( pColset->nCol==1 ){
|
||||||
|
assert( pPhrase->poslist.nSpace==0 );
|
||||||
|
pPhrase->poslist.n = fts5ExprExtractCol(&pPos, nPos, pColset->aiCol[0]);
|
||||||
|
pPhrase->poslist.p = (u8*)pPos;
|
||||||
|
}else if( rc==SQLITE_OK ){
|
||||||
|
rc = fts5ExprExtractColset(pColset, pPos, nPos, &pPhrase->poslist);
|
||||||
|
}
|
||||||
|
|
||||||
|
pNode->bNomatch = (pPhrase->poslist.n==0);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Argument pNode points to a NEAR node. All individual term iterators
|
** All individual term iterators in pNear are guaranteed to be valid when
|
||||||
** point to valid entries (not EOF).
|
** this function is called. This function checks if all term iterators
|
||||||
*
|
** point to the same rowid, and if not, advances them until they do.
|
||||||
** This function tests if the term iterators currently all point to the
|
** If an EOF is reached before this happens, *pbEof is set to true before
|
||||||
** same rowid, and if so, if the row matches the phrase and NEAR constraints.
|
** returning.
|
||||||
** If so, the pPhrase->poslist buffers are populated and the pNode->iRowid
|
|
||||||
** variable set before returning. Or, if the current combination of
|
|
||||||
** iterators is not a match, they are advanced until they are. If one of
|
|
||||||
** the iterators reaches EOF before a match is found, *pbEof is set to
|
|
||||||
** true before returning. The final values of the pPhrase->poslist and
|
|
||||||
** iRowid fields are undefined in this case.
|
|
||||||
**
|
**
|
||||||
** SQLITE_OK is returned if an error occurs, or an SQLite error code
|
** SQLITE_OK is returned if an error occurs, or an SQLite error code
|
||||||
** otherwise. It is not considered an error code if an iterator reaches
|
** otherwise. It is not considered an error code if an iterator reaches
|
||||||
** EOF.
|
** EOF.
|
||||||
*/
|
*/
|
||||||
static int fts5ExprNearNextMatch(
|
static int fts5ExprNearNextMatch(
|
||||||
Fts5Expr *pExpr, /* Expression that pNear is a part of */
|
Fts5Expr *pExpr, /* Expression pPhrase belongs to */
|
||||||
Fts5ExprNode *pNode /* The "NEAR" node (FTS5_STRING) */
|
Fts5ExprNode *pNode
|
||||||
){
|
){
|
||||||
|
Fts5ExprNearset *pNear = pNode->pNear;
|
||||||
|
Fts5ExprPhrase *pLeft = pNear->apPhrase[0];
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
|
i64 iLast; /* Lastest rowid any iterator points to */
|
||||||
|
int i, j; /* Phrase and token index, respectively */
|
||||||
|
int bMatch; /* True if all terms are at the same rowid */
|
||||||
|
|
||||||
assert( pNode->pNear );
|
assert( pNear->nPhrase>1 || pNear->apPhrase[0]->nTerm>1 );
|
||||||
while( 1 ){
|
|
||||||
|
|
||||||
/* Advance the iterators until they all point to the same rowid */
|
/* Initialize iLast, the "lastest" rowid any iterator points to. If the
|
||||||
rc = fts5ExprNearNextRowidMatch(pExpr, pNode);
|
** iterator skips through rowids in the default ascending order, this means
|
||||||
if( rc!=SQLITE_OK || pNode->bEof ) break;
|
** the maximum rowid. Or, if the iterator is "ORDER BY rowid DESC", then it
|
||||||
|
** means the minimum rowid. */
|
||||||
|
iLast = sqlite3Fts5IterRowid(pLeft->aTerm[0].pIter);
|
||||||
|
|
||||||
if( fts5ExprNearTest(&rc, pExpr, pNode) ) break;
|
do {
|
||||||
|
bMatch = 1;
|
||||||
/* If control flows to here, then the current rowid is not a match.
|
for(i=0; i<pNear->nPhrase; i++){
|
||||||
** Advance all term iterators in all phrases to the next rowid. */
|
Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
|
||||||
if( rc==SQLITE_OK ){
|
for(j=0; j<pPhrase->nTerm; j++){
|
||||||
rc = fts5ExprNearAdvanceFirst(pExpr, pNode, 0, 0);
|
Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter;
|
||||||
|
i64 iRowid = sqlite3Fts5IterRowid(pIter);
|
||||||
|
if( iRowid!=iLast ) bMatch = 0;
|
||||||
|
if( fts5ExprAdvanceto(pIter, pExpr->bDesc, &iLast,&rc,&pNode->bEof) ){
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
if( pNode->bEof || rc!=SQLITE_OK ) break;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}while( bMatch==0 );
|
||||||
|
|
||||||
|
pNode->bNomatch = (0==fts5ExprNearTest(&rc, pExpr, pNode));
|
||||||
|
pNode->iRowid = iLast;
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -939,6 +948,22 @@ static void fts5ExprSetEof(Fts5ExprNode *pNode){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fts5ExprNodeZeroPoslist(Fts5ExprNode *pNode){
|
||||||
|
if( pNode->eType==FTS5_STRING || pNode->eType==FTS5_TERM ){
|
||||||
|
Fts5ExprNearset *pNear = pNode->pNear;
|
||||||
|
int i;
|
||||||
|
for(i=0; i<pNear->nPhrase; i++){
|
||||||
|
Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
|
||||||
|
pPhrase->poslist.n = 0;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
int i;
|
||||||
|
for(i=0; i<pNode->nChild; i++){
|
||||||
|
fts5ExprNodeZeroPoslist(pNode->apChild[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int fts5ExprNodeNext(Fts5Expr*, Fts5ExprNode*, int, i64);
|
static int fts5ExprNodeNext(Fts5Expr*, Fts5ExprNode*, int, i64);
|
||||||
|
|
||||||
@ -956,6 +981,7 @@ static int fts5ExprAndNextRowid(
|
|||||||
|
|
||||||
assert( pAnd->bEof==0 );
|
assert( pAnd->bEof==0 );
|
||||||
do {
|
do {
|
||||||
|
pAnd->bNomatch = 0;
|
||||||
bMatch = 1;
|
bMatch = 1;
|
||||||
for(iChild=0; iChild<pAnd->nChild; iChild++){
|
for(iChild=0; iChild<pAnd->nChild; iChild++){
|
||||||
Fts5ExprNode *pChild = pAnd->apChild[iChild];
|
Fts5ExprNode *pChild = pAnd->apChild[iChild];
|
||||||
@ -983,9 +1009,16 @@ static int fts5ExprAndNextRowid(
|
|||||||
bMatch = 0;
|
bMatch = 0;
|
||||||
iLast = pChild->iRowid;
|
iLast = pChild->iRowid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( pChild->bNomatch ){
|
||||||
|
pAnd->bNomatch = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}while( bMatch==0 );
|
}while( bMatch==0 );
|
||||||
|
|
||||||
|
if( pAnd->bNomatch && pAnd!=pExpr->pRoot ){
|
||||||
|
fts5ExprNodeZeroPoslist(pAnd);
|
||||||
|
}
|
||||||
pAnd->iRowid = iLast;
|
pAnd->iRowid = iLast;
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
@ -1035,6 +1068,15 @@ static int fts5ExprNodeNext(
|
|||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
case FTS5_TERM: {
|
||||||
|
rc = fts5ExprNearAdvanceFirst(pExpr, pNode, bFromValid, iFrom);
|
||||||
|
if( pNode->bEof==0 ){
|
||||||
|
assert( rc==SQLITE_OK );
|
||||||
|
rc = fts5ExprTokenTest(pExpr, pNode);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
};
|
||||||
|
|
||||||
case FTS5_AND: {
|
case FTS5_AND: {
|
||||||
Fts5ExprNode *pLeft = pNode->apChild[0];
|
Fts5ExprNode *pLeft = pNode->apChild[0];
|
||||||
rc = fts5ExprNodeNext(pExpr, pLeft, bFromValid, iFrom);
|
rc = fts5ExprNodeNext(pExpr, pLeft, bFromValid, iFrom);
|
||||||
@ -1087,76 +1129,6 @@ static int fts5ExprNodeNext(
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fts5ExprNodeZeroPoslist(Fts5ExprNode *pNode){
|
|
||||||
if( pNode->eType==FTS5_STRING ){
|
|
||||||
Fts5ExprNearset *pNear = pNode->pNear;
|
|
||||||
int i;
|
|
||||||
for(i=0; i<pNear->nPhrase; i++){
|
|
||||||
Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
|
|
||||||
pPhrase->poslist.n = 0;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
int i;
|
|
||||||
for(i=0; i<pNode->nChild; i++){
|
|
||||||
fts5ExprNodeZeroPoslist(pNode->apChild[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int fts5ExprNodeTest(
|
|
||||||
int *pRc,
|
|
||||||
Fts5Expr *pExpr,
|
|
||||||
i64 iRowid,
|
|
||||||
Fts5ExprNode *pNode
|
|
||||||
){
|
|
||||||
int bRes = 0;
|
|
||||||
if( pNode->bEof || pNode->iRowid!=iRowid ){
|
|
||||||
bRes = 0;
|
|
||||||
}else {
|
|
||||||
switch( pNode->eType ){
|
|
||||||
case FTS5_STRING:
|
|
||||||
bRes = fts5ExprNearTest(pRc, pExpr, pNode);
|
|
||||||
if( *pRc ) bRes = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FTS5_AND: {
|
|
||||||
int i;
|
|
||||||
for(i=0; i<pNode->nChild; i++){
|
|
||||||
if( fts5ExprNodeTest(pRc, pExpr, iRowid, pNode->apChild[i])==0 ){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bRes = (i==pNode->nChild);
|
|
||||||
if( bRes==0 && i>0 ){
|
|
||||||
for(i=0; i<pNode->nChild; i++){
|
|
||||||
fts5ExprNodeZeroPoslist(pNode->apChild[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case FTS5_OR: {
|
|
||||||
int i;
|
|
||||||
for(i=0; i<pNode->nChild; i++){
|
|
||||||
if( fts5ExprNodeTest(pRc, pExpr, iRowid, pNode->apChild[i]) ){
|
|
||||||
bRes = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert( pNode->eType==FTS5_NOT );
|
|
||||||
assert( pNode->nChild==2 );
|
|
||||||
bRes = fts5ExprNodeTest(pRc, pExpr, iRowid, pNode->apChild[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return bRes;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** If pNode currently points to a match, this function returns SQLITE_OK
|
** If pNode currently points to a match, this function returns SQLITE_OK
|
||||||
@ -1172,10 +1144,13 @@ static int fts5ExprNodeNextMatch(
|
|||||||
switch( pNode->eType ){
|
switch( pNode->eType ){
|
||||||
|
|
||||||
case FTS5_STRING: {
|
case FTS5_STRING: {
|
||||||
#if 0
|
/* Advance the iterators until they all point to the same rowid */
|
||||||
rc = fts5ExprNearNextMatch(pExpr, pNode);
|
rc = fts5ExprNearNextMatch(pExpr, pNode);
|
||||||
#endif
|
break;
|
||||||
rc = fts5ExprNearNextRowidMatch(pExpr, pNode);
|
}
|
||||||
|
|
||||||
|
case FTS5_TERM: {
|
||||||
|
rc = fts5ExprTokenTest(pExpr, pNode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1187,14 +1162,17 @@ static int fts5ExprNodeNextMatch(
|
|||||||
case FTS5_OR: {
|
case FTS5_OR: {
|
||||||
Fts5ExprNode *pNext = pNode->apChild[0];
|
Fts5ExprNode *pNext = pNode->apChild[0];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for(i=1; i<pNode->nChild; i++){
|
for(i=1; i<pNode->nChild; i++){
|
||||||
Fts5ExprNode *pChild = pNode->apChild[i];
|
Fts5ExprNode *pChild = pNode->apChild[i];
|
||||||
if( fts5NodeCompare(pExpr, pNext, pChild)>0 ){
|
int cmp = fts5NodeCompare(pExpr, pNext, pChild);
|
||||||
|
if( cmp>0 || (cmp==0 && pChild->bNomatch==0) ){
|
||||||
pNext = pChild;
|
pNext = pChild;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pNode->iRowid = pNext->iRowid;
|
pNode->iRowid = pNext->iRowid;
|
||||||
pNode->bEof = pNext->bEof;
|
pNode->bEof = pNext->bEof;
|
||||||
|
pNode->bNomatch = pNext->bNomatch;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1210,7 +1188,7 @@ static int fts5ExprNodeNextMatch(
|
|||||||
cmp = fts5NodeCompare(pExpr, p1, p2);
|
cmp = fts5NodeCompare(pExpr, p1, p2);
|
||||||
}
|
}
|
||||||
assert( rc!=SQLITE_OK || cmp<=0 );
|
assert( rc!=SQLITE_OK || cmp<=0 );
|
||||||
if( 0==fts5ExprNodeTest(&rc, pExpr, p1->iRowid, p2) ) break;
|
if( cmp || p2->bNomatch ) break;
|
||||||
rc = fts5ExprNodeNext(pExpr, p1, 0, 0);
|
rc = fts5ExprNodeNext(pExpr, p1, 0, 0);
|
||||||
}
|
}
|
||||||
pNode->bEof = p1->bEof;
|
pNode->bEof = p1->bEof;
|
||||||
@ -1234,30 +1212,20 @@ static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){
|
|||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
pNode->bEof = 0;
|
pNode->bEof = 0;
|
||||||
|
|
||||||
if( pNode->eType==FTS5_STRING ){
|
if( Fts5NodeIsString(pNode) ){
|
||||||
|
|
||||||
/* Initialize all term iterators in the NEAR object. */
|
/* Initialize all term iterators in the NEAR object. */
|
||||||
rc = fts5ExprNearInitAll(pExpr, pNode);
|
rc = fts5ExprNearInitAll(pExpr, pNode);
|
||||||
|
|
||||||
/* Attempt to advance to the first match */
|
|
||||||
if( rc==SQLITE_OK && pNode->bEof==0 ){
|
|
||||||
#if 0
|
|
||||||
rc = fts5ExprNearNextMatch(pExpr, pNode);
|
|
||||||
#endif
|
|
||||||
rc = fts5ExprNearNextRowidMatch(pExpr, pNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
int i;
|
int i;
|
||||||
for(i=0; i<pNode->nChild && rc==SQLITE_OK; i++){
|
for(i=0; i<pNode->nChild && rc==SQLITE_OK; i++){
|
||||||
rc = fts5ExprNodeFirst(pExpr, pNode->apChild[i]);
|
rc = fts5ExprNodeFirst(pExpr, pNode->apChild[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pNode->iRowid = pNode->apChild[0]->iRowid;
|
pNode->iRowid = pNode->apChild[0]->iRowid;
|
||||||
|
}
|
||||||
|
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
rc = fts5ExprNodeNextMatch(pExpr, pNode);
|
rc = fts5ExprNodeNextMatch(pExpr, pNode);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1278,11 +1246,9 @@ int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, int bDesc){
|
|||||||
p->pIndex = pIdx;
|
p->pIndex = pIdx;
|
||||||
p->bDesc = bDesc;
|
p->bDesc = bDesc;
|
||||||
rc = fts5ExprNodeFirst(p, pRoot);
|
rc = fts5ExprNodeFirst(p, pRoot);
|
||||||
if( pRoot->bEof==0
|
|
||||||
&& 0==fts5ExprNodeTest(&rc, p, pRoot->iRowid, pRoot)
|
while( pRoot->bNomatch && rc==SQLITE_OK && pRoot->bEof==0 ){
|
||||||
&& rc==SQLITE_OK
|
rc = fts5ExprNodeNext(p, pRoot, 0, 0);
|
||||||
){
|
|
||||||
rc = sqlite3Fts5ExprNext(p);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
@ -1299,10 +1265,7 @@ int sqlite3Fts5ExprNext(Fts5Expr *p){
|
|||||||
Fts5ExprNode *pRoot = p->pRoot;
|
Fts5ExprNode *pRoot = p->pRoot;
|
||||||
do {
|
do {
|
||||||
rc = fts5ExprNodeNext(p, pRoot, 0, 0);
|
rc = fts5ExprNodeNext(p, pRoot, 0, 0);
|
||||||
}while( pRoot->bEof==0
|
}while( pRoot->bNomatch && pRoot->bEof==0 && rc==SQLITE_OK );
|
||||||
&& fts5ExprNodeTest(&rc, p, pRoot->iRowid, p->pRoot)==0
|
|
||||||
&& rc==SQLITE_OK
|
|
||||||
);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1699,6 +1662,9 @@ Fts5ExprNode *sqlite3Fts5ParseNode(
|
|||||||
for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
|
for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
|
||||||
pNear->apPhrase[iPhrase]->pNode = pRet;
|
pNear->apPhrase[iPhrase]->pNode = pRet;
|
||||||
}
|
}
|
||||||
|
if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1 ){
|
||||||
|
pRet->eType = FTS5_TERM;
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
fts5ExprAddChildren(pRet, pLeft);
|
fts5ExprAddChildren(pRet, pLeft);
|
||||||
fts5ExprAddChildren(pRet, pRight);
|
fts5ExprAddChildren(pRet, pRight);
|
||||||
@ -1762,7 +1728,7 @@ static char *fts5ExprPrintTcl(
|
|||||||
Fts5ExprNode *pExpr
|
Fts5ExprNode *pExpr
|
||||||
){
|
){
|
||||||
char *zRet = 0;
|
char *zRet = 0;
|
||||||
if( pExpr->eType==FTS5_STRING ){
|
if( pExpr->eType==FTS5_STRING || pExpr->eType==FTS5_TERM ){
|
||||||
Fts5ExprNearset *pNear = pExpr->pNear;
|
Fts5ExprNearset *pNear = pExpr->pNear;
|
||||||
int i;
|
int i;
|
||||||
int iTerm;
|
int iTerm;
|
||||||
@ -1836,7 +1802,7 @@ static char *fts5ExprPrintTcl(
|
|||||||
|
|
||||||
static char *fts5ExprPrint(Fts5Config *pConfig, Fts5ExprNode *pExpr){
|
static char *fts5ExprPrint(Fts5Config *pConfig, Fts5ExprNode *pExpr){
|
||||||
char *zRet = 0;
|
char *zRet = 0;
|
||||||
if( pExpr->eType==FTS5_STRING ){
|
if( pExpr->eType==FTS5_STRING || pExpr->eType==FTS5_TERM ){
|
||||||
Fts5ExprNearset *pNear = pExpr->pNear;
|
Fts5ExprNearset *pNear = pExpr->pNear;
|
||||||
int i;
|
int i;
|
||||||
int iTerm;
|
int iTerm;
|
||||||
@ -1895,7 +1861,8 @@ static char *fts5ExprPrint(Fts5Config *pConfig, Fts5ExprNode *pExpr){
|
|||||||
sqlite3_free(zRet);
|
sqlite3_free(zRet);
|
||||||
zRet = 0;
|
zRet = 0;
|
||||||
}else{
|
}else{
|
||||||
int b = (pExpr->apChild[i]->eType!=FTS5_STRING);
|
int e = pExpr->apChild[i]->eType;
|
||||||
|
int b = (e!=FTS5_STRING && e!=FTS5_TERM);
|
||||||
zRet = fts5PrintfAppend(zRet, "%s%s%z%s",
|
zRet = fts5PrintfAppend(zRet, "%s%s%z%s",
|
||||||
(i==0 ? "" : zOp),
|
(i==0 ? "" : zOp),
|
||||||
(b?"(":""), z, (b?")":"")
|
(b?"(":""), z, (b?")":"")
|
||||||
|
@ -63,6 +63,7 @@
|
|||||||
%left OR.
|
%left OR.
|
||||||
%left AND.
|
%left AND.
|
||||||
%left NOT.
|
%left NOT.
|
||||||
|
%left TERM.
|
||||||
%left COLON.
|
%left COLON.
|
||||||
|
|
||||||
input ::= expr(X). { sqlite3Fts5ParseFinished(pParse, X); }
|
input ::= expr(X). { sqlite3Fts5ParseFinished(pParse, X); }
|
||||||
|
@ -290,34 +290,36 @@ for {set fold 0} {$fold < 3} {incr fold} {
|
|||||||
DELETE FROM tt;
|
DELETE FROM tt;
|
||||||
}
|
}
|
||||||
foreach {rowid a b c d e f} [string map $map $data] {
|
foreach {rowid a b c d e f} [string map $map $data] {
|
||||||
|
if {$rowid==-4703774} {
|
||||||
execsql {
|
execsql {
|
||||||
INSERT INTO tt(rowid, a, b, c, d, e, f)
|
INSERT INTO tt(rowid, a, b, c, d, e, f)
|
||||||
VALUES($rowid, $a, $b, $c, $d, $e, $f)
|
VALUES($rowid, $a, $b, $c, $d, $e, $f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
execsql COMMIT
|
execsql COMMIT
|
||||||
|
|
||||||
|
|
||||||
foreach {tn expr} {
|
foreach {tn expr} {
|
||||||
3.1 { [a] : x }
|
A.1 { [a] : x }
|
||||||
3.2 { [a b] : x }
|
A.2 { [a b] : x }
|
||||||
3.3 { [a b f] : x }
|
A.3 { [a b f] : x }
|
||||||
3.4 { [f a b] : x }
|
A.4 { [f a b] : x }
|
||||||
3.5 { [f a b] : x y }
|
A.5 { [f a b] : x y }
|
||||||
3.6 { [f a b] : x + y }
|
A.6 { [f a b] : x + y }
|
||||||
3.7 { [c a b] : x + c }
|
A.7 { [c a b] : x + c }
|
||||||
3.8 { [c d] : "l m" }
|
A.8 { [c d] : "l m" }
|
||||||
3.9 { [c e] : "l m" }
|
A.9 { [c e] : "l m" }
|
||||||
|
|
||||||
4.1 { a NOT b }
|
B.1 { a NOT b }
|
||||||
4.2 { a NOT a:b }
|
B.2 { a NOT a:b }
|
||||||
4.3 { a OR (b AND c) }
|
B.3 { a OR (b AND c) }
|
||||||
4.4 { a OR (b AND [a b c]:c) }
|
B.4 { a OR (b AND [a b c]:c) }
|
||||||
4.5 { a OR "b c" }
|
B.5 { a OR "b c" }
|
||||||
4.6 { a OR b OR c }
|
B.6 { a OR b OR c }
|
||||||
|
|
||||||
5.1 { a OR (b AND "b c") }
|
C.1 { a OR (b AND "b c") }
|
||||||
5.2 { a OR (b AND "z c") }
|
C.2 { a OR (b AND "z c") }
|
||||||
} {
|
} {
|
||||||
do_auto_test 3.$fold.$tn $expr
|
do_auto_test 3.$fold.$tn $expr
|
||||||
}
|
}
|
||||||
|
16
manifest
16
manifest
@ -1,5 +1,5 @@
|
|||||||
C Improve\sperformance\sof\sthe\sfts5\sAND\soperator.
|
C Reimplement\s[ec69e09a]\sso\sthat\seach\scall\sto\sthe\sxNext()\smethod\sdoes\snot\sinvolve\stwo\siterations\sof\sthe\smatch\sexpression\stree\s(only\sone).
|
||||||
D 2015-06-01T19:17:06.810
|
D 2015-06-02T17:57:01.304
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 2c28e557780395095c307a6e5cb539419027eb5e
|
F Makefile.in 2c28e557780395095c307a6e5cb539419027eb5e
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@ -111,7 +111,7 @@ F ext/fts5/fts5Int.h 4c677f3b797acde90ba1b7730eca6a32e7def742
|
|||||||
F ext/fts5/fts5_aux.c d53f00f31ad615ca4f139dd8751f9041afa00971
|
F ext/fts5/fts5_aux.c d53f00f31ad615ca4f139dd8751f9041afa00971
|
||||||
F ext/fts5/fts5_buffer.c 9ec57c75c81e81dca118568876b1caead0aadadf
|
F ext/fts5/fts5_buffer.c 9ec57c75c81e81dca118568876b1caead0aadadf
|
||||||
F ext/fts5/fts5_config.c 11f969ed711a0a8b611d47431d74c372ad78c713
|
F ext/fts5/fts5_config.c 11f969ed711a0a8b611d47431d74c372ad78c713
|
||||||
F ext/fts5/fts5_expr.c e68f969e9276d312554195a158240f9705c374c1
|
F ext/fts5/fts5_expr.c ae3cff45a4f36d0bc7561675fbd081d6a1df78b3
|
||||||
F ext/fts5/fts5_hash.c c1cfdb2cae0fad00b06fae38a40eaf9261563ccc
|
F ext/fts5/fts5_hash.c c1cfdb2cae0fad00b06fae38a40eaf9261563ccc
|
||||||
F ext/fts5/fts5_index.c 7cea402924cd3d8cd5943a7f9514c9153696571b
|
F ext/fts5/fts5_index.c 7cea402924cd3d8cd5943a7f9514c9153696571b
|
||||||
F ext/fts5/fts5_storage.c 04e6717656b78eb230a1c730cac3b935eb94889b
|
F ext/fts5/fts5_storage.c 04e6717656b78eb230a1c730cac3b935eb94889b
|
||||||
@ -120,7 +120,7 @@ F ext/fts5/fts5_tokenize.c 97251d68d7a6a9415bde1203f9382864dfc1f989
|
|||||||
F ext/fts5/fts5_unicode2.c da3cf712f05cd8347c8c5bc00964cc0361c88da9
|
F ext/fts5/fts5_unicode2.c da3cf712f05cd8347c8c5bc00964cc0361c88da9
|
||||||
F ext/fts5/fts5_varint.c 366452037bf9a000c351374b489badc1b3541796
|
F ext/fts5/fts5_varint.c 366452037bf9a000c351374b489badc1b3541796
|
||||||
F ext/fts5/fts5_vocab.c 1f8543b2c1ae4427f127a911bc8e60873fcd7bf9
|
F ext/fts5/fts5_vocab.c 1f8543b2c1ae4427f127a911bc8e60873fcd7bf9
|
||||||
F ext/fts5/fts5parse.y 4ee667932d561a150d96483cf563281b95a9e523
|
F ext/fts5/fts5parse.y 7f256d4de575f60f06c7c42c1514537168f0c035
|
||||||
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
|
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
|
||||||
F ext/fts5/test/fts5_common.tcl 0b465b1127adcd1c8131f3454ab4264a6964674c
|
F ext/fts5/test/fts5_common.tcl 0b465b1127adcd1c8131f3454ab4264a6964674c
|
||||||
F ext/fts5/test/fts5aa.test 5f73afe6a1394fdba9bc18302876ded81021bee6
|
F ext/fts5/test/fts5aa.test 5f73afe6a1394fdba9bc18302876ded81021bee6
|
||||||
@ -135,7 +135,7 @@ F ext/fts5/test/fts5ai.test f20e53bbf0c55bc596f1fd47f2740dae028b8f37
|
|||||||
F ext/fts5/test/fts5aj.test 05b569f5c16ea3098fb1984eec5cf50dbdaae5d8
|
F ext/fts5/test/fts5aj.test 05b569f5c16ea3098fb1984eec5cf50dbdaae5d8
|
||||||
F ext/fts5/test/fts5ak.test 7b8c5df96df599293f920b7e5521ebc79f647592
|
F ext/fts5/test/fts5ak.test 7b8c5df96df599293f920b7e5521ebc79f647592
|
||||||
F ext/fts5/test/fts5al.test fc60ebeac9d8e366e71309d4c31fa72199d711d7
|
F ext/fts5/test/fts5al.test fc60ebeac9d8e366e71309d4c31fa72199d711d7
|
||||||
F ext/fts5/test/fts5auto.test 3810c1c4928be0161b87dfc479ecf1b873f37c6c
|
F ext/fts5/test/fts5auto.test 04286120430fea482ee4b3756ce1941acd3d3962
|
||||||
F ext/fts5/test/fts5aux.test e5631607bbc05ac1c38cf7d691000509aca71ef3
|
F ext/fts5/test/fts5aux.test e5631607bbc05ac1c38cf7d691000509aca71ef3
|
||||||
F ext/fts5/test/fts5auxdata.test c69b86092bf1a157172de5f9169731af3403179b
|
F ext/fts5/test/fts5auxdata.test c69b86092bf1a157172de5f9169731af3403179b
|
||||||
F ext/fts5/test/fts5bigpl.test b1cfd00561350ab04994ba7dd9d48468e5e0ec3b
|
F ext/fts5/test/fts5bigpl.test b1cfd00561350ab04994ba7dd9d48468e5e0ec3b
|
||||||
@ -1333,7 +1333,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||||
P ec69e09a55b4daf1c40aeaaf9ee95091fe86f5c0
|
P b43e9a5b7a0483ccb102316a4dbc5e32b5bc69ec
|
||||||
R acaa89910e5f0d02d970b6387ace6327
|
R bd2db0e568f1313170e13c32f86585fb
|
||||||
U dan
|
U dan
|
||||||
Z 115cb3cf0377892edfa5b36bfcc4447b
|
Z 85ab84df13bd96f34cdaff4b243d8a96
|
||||||
|
@ -1 +1 @@
|
|||||||
b43e9a5b7a0483ccb102316a4dbc5e32b5bc69ec
|
80fe305b3eefb17310a9d6185d1c8cd73ee38b1e
|
Loading…
x
Reference in New Issue
Block a user