return rc;
}
+/*
+** 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
+** to point to the sub-position-list for that column and the number of
+** bytes in it returned. Or, if the argument position list does not
+** contain any entries for column iCol, return 0.
+*/
+static int fts5ExprExtractCol(
+ const u8 **pa, /* IN/OUT: Pointer to poslist */
+ int n, /* IN: Size of poslist in bytes */
+ int iCol /* Column to extract from poslist */
+){
+ int ii;
+ int iCurrent = 0;
+ const u8 *p = *pa;
+ const u8 *pEnd = &p[n]; /* One byte past end of position list */
+ u8 prev = 0;
+
+ while( iCol!=iCurrent ){
+ /* Advance pointer p until it points to pEnd or an 0x01 byte that is
+ ** not part of a varint */
+ while( !(prev & 0x80) && *p!=0x01 ){
+ prev = *p++;
+ if( p==pEnd ) return 0;
+ }
+ *pa = p++;
+ p += getVarint32(p, iCurrent);
+ }
+
+ /* Advance pointer p until it points to pEnd or an 0x01 byte that is
+ ** not part of a varint */
+ while( p<pEnd && !(prev & 0x80) && *p!=0x01 ){
+ prev = *p++;
+ }
+ return p - (*pa);
+}
+
+
+
/*
** Argument pNode points to a NEAR node. All individual term iterators
** point to valid entries (not EOF).
Fts5ExprNode *pNode /* The "NEAR" node (FTS5_STRING) */
){
Fts5ExprNearset *pNear = pNode->pNear;
+ int rc = SQLITE_OK;
- if( pNear->nPhrase==1
- && pNear->apPhrase[0]->nTerm==1
- && pNear->iCol<0
- ){
- /* If this "NEAR" object is actually a single phrase that consists of
- ** a single term only, then the row that it currently points to must
- ** be a match. All that is required is to populate pPhrase->poslist
- ** with the position-list data for the only term. */
- Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
- Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter;
- assert( pPhrase->poslist.nSpace==0 );
- return sqlite3Fts5IterPoslist(pIter,
- (const u8**)&pPhrase->poslist.p, &pPhrase->poslist.n, &pNode->iRowid
- );
- }else{
- int rc = SQLITE_OK;
+ while( 1 ){
+ int i;
- while( 1 ){
- int i;
+ if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1 ){
+ /* If this "NEAR" object is actually a single phrase that consists
+ ** of a single term only, then 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. */
+ Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
+ Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter;
+ assert( pPhrase->poslist.nSpace==0 );
+ rc = sqlite3Fts5IterPoslist(pIter,
+ (const u8**)&pPhrase->poslist.p, &pPhrase->poslist.n, &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( pNear->iCol<0 ) return rc;
+
+ pPhrase->poslist.n = fts5ExprExtractCol(
+ (const u8**)&pPhrase->poslist.p,
+ pPhrase->poslist.n,
+ pNear->iCol
+ );
+ if( pPhrase->poslist.n ) return rc;
+ }else{
/* Advance the iterators until they all point to the same rowid */
rc = fts5ExprNearNextRowidMatch(pExpr, pNode);
}else{
rc = sqlite3Fts5IterPoslistBuffer(
pPhrase->aTerm[0].pIter, &pPhrase->poslist
- );
+ );
}
}
}
if( rc!=SQLITE_OK || bMatch ) break;
}
-
- /* If control flows to here, then the current rowid is not a match.
- ** Advance all term iterators in all phrases to the next rowid. */
- if( rc==SQLITE_OK ){
- rc = fts5ExprNearAdvanceFirst(pExpr, pNode, 0, 0);
- }
- if( pNode->bEof || rc!=SQLITE_OK ) break;
}
- return rc;
+ /* If control flows to here, then the current rowid is not a match.
+ ** Advance all term iterators in all phrases to the next rowid. */
+ if( rc==SQLITE_OK ){
+ rc = fts5ExprNearAdvanceFirst(pExpr, pNode, 0, 0);
+ }
+ if( pNode->bEof || rc!=SQLITE_OK ) break;
}
+
+ return rc;
}
/*
-C Remove\ssome\sdead\scode\sfrom\sfts5.\sAdd\sauxiliary\sfunction\sapi\stests\sto\sthe\ssame.
-D 2015-05-28T14:37:26.732
+C Optimizations\sfor\sfts5\squeries\sthat\smatch\sagainst\sa\sspecific\scolumn.
+D 2015-05-28T19:57:12.367
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 2c28e557780395095c307a6e5cb539419027eb5e
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F ext/fts5/fts5_aux.c d53f00f31ad615ca4f139dd8751f9041afa00971
F ext/fts5/fts5_buffer.c 861599a0abe2383f0cd0352c57001140a26b0930
F ext/fts5/fts5_config.c 11f969ed711a0a8b611d47431d74c372ad78c713
-F ext/fts5/fts5_expr.c a8b31d363c02108dae01e13948661859f449ebb9
+F ext/fts5/fts5_expr.c c94983eaff58391d7c0d62e99de917cecd0f1dbc
F ext/fts5/fts5_hash.c 54dd25348a46ea62ea96322c572e08cd1fb37304
F ext/fts5/fts5_index.c a693ba741b82539da5779329214e5d2609e82e5f
F ext/fts5/fts5_storage.c 5d2b51adb304643d8f825ba89283d628418b20c2
F ext/fts5/fts5parse.y 777da8e5819f75c217982c79c29d014c293acac9
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
F ext/fts5/test/fts5_common.tcl 6d663e8c3d8409857363f66560df96b8ca813e79
-F ext/fts5/test/fts5aa.test 26f1a462213f3aa067c208bd508d6218c54a620f
+F ext/fts5/test/fts5aa.test 5f73afe6a1394fdba9bc18302876ded81021bee6
F ext/fts5/test/fts5ab.test 6fe3a56731d15978afbb74ae51b355fc9310f2ad
F ext/fts5/test/fts5ac.test 05008e00bd2761cc45df838a0988ecf318cbe1fd
F ext/fts5/test/fts5ad.test 312f3c8ed9592533499c5b94d2059ae6382913a0
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P aef89d9f6aa536efee347367558cf5d4ea81b238
-R bb8e2d4390fd848d148991824b1dfd3a
+P 0f9df202cc58097afddb8dad662b7c7fdc2c7d0c
+R f25569d3bfd1393da78f5986e0e8acff
U dan
-Z cb932577f097e506aa4f837dda1f2a1b
+Z d652fde1b36e85f62688dc3a9737ccda