From: drh Date: Wed, 13 Sep 2006 16:02:43 +0000 (+0000) Subject: Implementation of "column:" modifiers in FTS1 queries. (CVS 3411) X-Git-Tag: version-3.6.10~2756 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a3baa963bc87a58d0d0c37fb039fcaae225216ab;p=thirdparty%2Fsqlite.git Implementation of "column:" modifiers in FTS1 queries. (CVS 3411) FossilOrigin-Name: 820634f71e3a3499994f82b56b784d22a7e3cdcf --- diff --git a/ext/fts1/fts1.c b/ext/fts1/fts1.c index 5b6f0da80d..831322b37c 100644 --- a/ext/fts1/fts1.c +++ b/ext/fts1/fts1.c @@ -1956,9 +1956,10 @@ static int fulltextNext(sqlite3_vtab_cursor *pCursor){ ** the following structure. */ typedef struct QueryTerm { - int nPhrase; /* How many following terms are part of the same phrase */ - int isOr; /* this term is preceded by "OR" */ - int isNot; /* this term is preceded by "-" */ + short int nPhrase; /* How many following terms are part of the same phrase */ + short int iColumn; /* Column of the index that must match this term */ + signed char isOr; /* this term is preceded by "OR" */ + signed char isNot; /* this term is preceded by "-" */ char *pTerm; /* text of the term. '\000' terminated. malloced */ int nTerm; /* Number of bytes in pTerm[] */ } QueryTerm; @@ -2028,9 +2029,11 @@ static int docListOfTerm( * */ typedef struct Query { + fulltext_vtab *pFts; /* The full text index */ int nTerms; /* Number of terms in the query */ QueryTerm *pTerms; /* Array of terms. Space obtained from malloc() */ int nextIsOr; /* Set the isOr flag on the next inserted term */ + int iColumn; /* Text word parsed must be in this column */ } Query; /* Add a new term pTerm[0..nTerm-1] to the query *q. @@ -2051,6 +2054,8 @@ static void queryAdd(Query *q, const char *pTerm, int nTerm){ t->nTerm = nTerm; t->isOr = q->nextIsOr; q->nextIsOr = 0; + t->iColumn = q->iColumn; + q->iColumn = -1; } /* Free all of the memory that was malloced in order to build *q. @@ -2063,6 +2068,26 @@ static void queryDestroy(Query *q){ free(q->pTerms); } +/* +** Check to see if the string zToken[0...nToken-1] matches any +** column name in the virtual table. If it does, +** return the zero-indexed column number. If not, return -1. +*/ +static int checkColumnSpecifier( + fulltext_vtab *pVtab, /* The virtual table */ + const char *zToken, /* Text of the token */ + int nToken /* Number of characters in the token */ +){ + int i; + for(i=0; inColumn; i++){ + if( memcmp(pVtab->azColumn[i], zToken, nToken)==0 + && pVtab->azColumn[i][nToken]==0 ){ + return i; + } + } + return -1; +} + /* ** Parse the text at pSegment[0..nSegment-1]. Add additional terms ** to the query being assemblied in pQuery. @@ -2082,6 +2107,7 @@ static int tokenizeSegment( const sqlite3_tokenizer_module *pModule = pTokenizer->pModule; sqlite3_tokenizer_cursor *pCursor; int firstIndex = pQuery->nTerms; + int iCol; int rc = pModule->xOpen(pTokenizer, pSegment, nSegment, &pCursor); if( rc!=SQLITE_OK ) return rc; @@ -2095,6 +2121,12 @@ static int tokenizeSegment( &pToken, &nToken, &iBegin, &iEnd, &iPos); if( rc!=SQLITE_OK ) break; + if( !inPhrase && + pSegment[iEnd]==':' && + (iCol = checkColumnSpecifier(pQuery->pFts, pToken, nToken))>=0 ){ + pQuery->iColumn = iCol; + continue; + } if( !inPhrase && pQuery->nTerms>0 && nToken==2 && pSegment[iBegin]=='O' && pSegment[iBegin+1]=='R' ){ pQuery->nextIsOr = 1; @@ -2123,6 +2155,8 @@ static int parseQuery(fulltext_vtab *v, const char *pInput, int nInput, pQuery->nTerms = 0; pQuery->pTerms = NULL; pQuery->nextIsOr = 0; + pQuery->iColumn = -1; + pQuery->pFts = v; for(iInput=0; iInput=nColumn +** they are allowed to match against any column. */ static int fulltextQuery(fulltext_vtab *v, int iColumn, const char *pInput, int nInput, DocList **pResult){ @@ -2157,6 +2194,7 @@ static int fulltextQuery(fulltext_vtab *v, int iColumn, DocList *pLeft = NULL; DocList *pRight, *pNew; int nNot = 0; + int iCol; rc = parseQuery(v, pInput, nInput, &q); if( rc!=SQLITE_OK ) return rc; @@ -2170,7 +2208,9 @@ static int fulltextQuery(fulltext_vtab *v, int iColumn, continue; } - rc = docListOfTerm(v, iColumn, &q.pTerms[i], &pRight); + iCol = q.pTerms[i].iColumn; + if( iCol<0 ) iCol = iColumn; + rc = docListOfTerm(v, iCol, &q.pTerms[i], &pRight); if( rc ){ queryDestroy(&q); return rc; @@ -2198,7 +2238,9 @@ static int fulltextQuery(fulltext_vtab *v, int iColumn, /* Do the EXCEPT terms */ for(i=0; i