OLD | NEW |
---|---|
1 /* fts2 has a design flaw which can lead to database corruption (see | 1 /* fts2 has a design flaw which can lead to database corruption (see |
2 ** below). It is recommended not to use it any longer, instead use | 2 ** below). It is recommended not to use it any longer, instead use |
3 ** fts3 (or higher). If you believe that your use of fts2 is safe, | 3 ** fts3 (or higher). If you believe that your use of fts2 is safe, |
4 ** add -DSQLITE_ENABLE_BROKEN_FTS2=1 to your CFLAGS. | 4 ** add -DSQLITE_ENABLE_BROKEN_FTS2=1 to your CFLAGS. |
5 */ | 5 */ |
6 #if (!defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2)) \ | 6 #if (!defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2)) \ |
7 && !defined(SQLITE_ENABLE_BROKEN_FTS2) | 7 && !defined(SQLITE_ENABLE_BROKEN_FTS2) |
8 #error fts2 has a design flaw and has been deprecated. | 8 #error fts2 has a design flaw and has been deprecated. |
9 #endif | 9 #endif |
10 /* The flaw is that fts2 uses the content table's unaliased rowid as | 10 /* The flaw is that fts2 uses the content table's unaliased rowid as |
(...skipping 3520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3531 sqlite3_tokenizer *pTokenizer, /* The tokenizer to use */ | 3531 sqlite3_tokenizer *pTokenizer, /* The tokenizer to use */ |
3532 const char *pSegment, int nSegment, /* Query expression being parsed */ | 3532 const char *pSegment, int nSegment, /* Query expression being parsed */ |
3533 int inPhrase, /* True if within "..." */ | 3533 int inPhrase, /* True if within "..." */ |
3534 Query *pQuery /* Append results here */ | 3534 Query *pQuery /* Append results here */ |
3535 ){ | 3535 ){ |
3536 const sqlite3_tokenizer_module *pModule = pTokenizer->pModule; | 3536 const sqlite3_tokenizer_module *pModule = pTokenizer->pModule; |
3537 sqlite3_tokenizer_cursor *pCursor; | 3537 sqlite3_tokenizer_cursor *pCursor; |
3538 int firstIndex = pQuery->nTerms; | 3538 int firstIndex = pQuery->nTerms; |
3539 int iCol; | 3539 int iCol; |
3540 int nTerm = 1; | 3540 int nTerm = 1; |
3541 int iEndLast = -1; | |
3541 | 3542 |
3542 int rc = pModule->xOpen(pTokenizer, pSegment, nSegment, &pCursor); | 3543 int rc = pModule->xOpen(pTokenizer, pSegment, nSegment, &pCursor); |
3543 if( rc!=SQLITE_OK ) return rc; | 3544 if( rc!=SQLITE_OK ) return rc; |
3544 pCursor->pTokenizer = pTokenizer; | 3545 pCursor->pTokenizer = pTokenizer; |
3545 | 3546 |
3546 while( 1 ){ | 3547 while( 1 ){ |
3547 const char *pToken; | 3548 const char *pToken; |
3548 int nToken, iBegin, iEnd, iPos; | 3549 int nToken, iBegin, iEnd, iPos; |
3549 | 3550 |
3550 rc = pModule->xNext(pCursor, | 3551 rc = pModule->xNext(pCursor, |
3551 &pToken, &nToken, | 3552 &pToken, &nToken, |
3552 &iBegin, &iEnd, &iPos); | 3553 &iBegin, &iEnd, &iPos); |
3553 if( rc!=SQLITE_OK ) break; | 3554 if( rc!=SQLITE_OK ) break; |
3554 if( !inPhrase && | 3555 if( !inPhrase && |
3555 pSegment[iEnd]==':' && | 3556 pSegment[iEnd]==':' && |
3556 (iCol = checkColumnSpecifier(pQuery->pFts, pToken, nToken))>=0 ){ | 3557 (iCol = checkColumnSpecifier(pQuery->pFts, pToken, nToken))>=0 ){ |
3557 pQuery->nextColumn = iCol; | 3558 pQuery->nextColumn = iCol; |
3558 continue; | 3559 continue; |
3559 } | 3560 } |
3560 if( !inPhrase && pQuery->nTerms>0 && nToken==2 | 3561 if( !inPhrase && pQuery->nTerms>0 && nToken==2 |
3561 && pSegment[iBegin]=='O' && pSegment[iBegin+1]=='R' ){ | 3562 && pSegment[iBegin]=='O' && pSegment[iBegin+1]=='R' ){ |
3562 pQuery->nextIsOr = 1; | 3563 pQuery->nextIsOr = 1; |
3563 continue; | 3564 continue; |
3564 } | 3565 } |
3565 | 3566 |
3566 // If a tokenizer recognizes "*" as a separate word, we mark the word | 3567 // If a tokenizer recognizes "*" as a separate word, we mark the word |
3567 // before it as a prefix search. The other isPrefix code below that tests | 3568 // before it as a prefix search. The other isPrefix code below that tests |
3568 // for a word that's tokenized with the star as its last character. | 3569 // for a word that's tokenized with the star as its last character. |
3569 // TODO(evanm): this is incorrect in that "foo *" parses as "foo*". | 3570 if( pQuery->nTerms>0 && nToken==1 && pSegment[iBegin]=='*' && |
3570 if( pQuery->nTerms>0 && nToken==1 && pSegment[iBegin]=='*' ){ | 3571 iEndLast==iBegin){ |
Evan Martin
2008/12/17 00:28:11
tabbing off here?
is iEndLast supposed to be one
Matt Perry
2008/12/17 00:29:58
fixed.. though there doesn't seem to be a consiste
| |
3571 pQuery->pTerms[pQuery->nTerms-1].isPrefix = 1; | 3572 pQuery->pTerms[pQuery->nTerms-1].isPrefix = 1; |
3572 continue; | 3573 continue; |
3573 } | 3574 } |
3574 | 3575 iEndLast = iEnd; |
3576 | |
3575 queryAdd(pQuery, pToken, nToken); | 3577 queryAdd(pQuery, pToken, nToken); |
3576 if( !inPhrase && iBegin>0 && pSegment[iBegin-1]=='-' ){ | 3578 if( !inPhrase && iBegin>0 && pSegment[iBegin-1]=='-' ){ |
3577 pQuery->pTerms[pQuery->nTerms-1].isNot = 1; | 3579 pQuery->pTerms[pQuery->nTerms-1].isNot = 1; |
3578 } | 3580 } |
3579 if( iEnd<nSegment && pSegment[iEnd]=='*' ){ | 3581 if( iEnd<nSegment && pSegment[iEnd]=='*' ){ |
3580 pQuery->pTerms[pQuery->nTerms-1].isPrefix = 1; | 3582 pQuery->pTerms[pQuery->nTerms-1].isPrefix = 1; |
3581 } | 3583 } |
3582 pQuery->pTerms[pQuery->nTerms-1].iPhrase = nTerm; | 3584 pQuery->pTerms[pQuery->nTerms-1].iPhrase = nTerm; |
3583 if( inPhrase ){ | 3585 if( inPhrase ){ |
3584 nTerm++; | 3586 nTerm++; |
(...skipping 3150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6735 sqlite3 *db, | 6737 sqlite3 *db, |
6736 char **pzErrMsg, | 6738 char **pzErrMsg, |
6737 const sqlite3_api_routines *pApi | 6739 const sqlite3_api_routines *pApi |
6738 ){ | 6740 ){ |
6739 SQLITE_EXTENSION_INIT2(pApi) | 6741 SQLITE_EXTENSION_INIT2(pApi) |
6740 return sqlite3Fts2Init(db); | 6742 return sqlite3Fts2Init(db); |
6741 } | 6743 } |
6742 #endif | 6744 #endif |
6743 | 6745 |
6744 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */ | 6746 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */ |
OLD | NEW |