OLD | NEW |
1 /* | 1 /* |
2 ** 2015 Aug 04 | 2 ** 2015 Aug 04 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
(...skipping 23 matching lines...) Expand all Loading... |
34 ** NEAR constraints are not considered. But for the number of hits in | 34 ** NEAR constraints are not considered. But for the number of hits in |
35 ** the current row, they are. | 35 ** the current row, they are. |
36 ** | 36 ** |
37 ** This file exports a single function that may be called to register the | 37 ** This file exports a single function that may be called to register the |
38 ** matchinfo() implementation with a database handle: | 38 ** matchinfo() implementation with a database handle: |
39 ** | 39 ** |
40 ** int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db); | 40 ** int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db); |
41 */ | 41 */ |
42 | 42 |
43 | 43 |
44 #ifdef SQLITE_TEST | |
45 #ifdef SQLITE_ENABLE_FTS5 | 44 #ifdef SQLITE_ENABLE_FTS5 |
46 | 45 |
47 #include "fts5.h" | 46 #include "fts5.h" |
48 #include <tcl.h> | |
49 #include <assert.h> | 47 #include <assert.h> |
50 #include <string.h> | 48 #include <string.h> |
51 | 49 |
52 typedef struct Fts5MatchinfoCtx Fts5MatchinfoCtx; | 50 typedef struct Fts5MatchinfoCtx Fts5MatchinfoCtx; |
| 51 |
| 52 #ifndef SQLITE_AMALGAMATION |
53 typedef unsigned int u32; | 53 typedef unsigned int u32; |
| 54 #endif |
54 | 55 |
55 struct Fts5MatchinfoCtx { | 56 struct Fts5MatchinfoCtx { |
56 int nCol; /* Number of cols in FTS5 table */ | 57 int nCol; /* Number of cols in FTS5 table */ |
57 int nPhrase; /* Number of phrases in FTS5 query */ | 58 int nPhrase; /* Number of phrases in FTS5 query */ |
58 char *zArg; /* nul-term'd copy of 2nd arg */ | 59 char *zArg; /* nul-term'd copy of 2nd arg */ |
59 int nRet; /* Number of elements in aRet[] */ | 60 int nRet; /* Number of elements in aRet[] */ |
60 u32 *aRet; /* Array of 32-bit unsigned ints to return */ | 61 u32 *aRet; /* Array of 32-bit unsigned ints to return */ |
61 }; | 62 }; |
62 | 63 |
63 | 64 |
64 | 65 |
65 /* | 66 /* |
66 ** Return a pointer to the fts5_api pointer for database connection db. | 67 ** Return a pointer to the fts5_api pointer for database connection db. |
67 ** If an error occurs, return NULL and leave an error in the database | 68 ** If an error occurs, return NULL and leave an error in the database |
68 ** handle (accessible using sqlite3_errcode()/errmsg()). | 69 ** handle (accessible using sqlite3_errcode()/errmsg()). |
69 */ | 70 */ |
70 static fts5_api *fts5_api_from_db(sqlite3 *db){ | 71 static int fts5_api_from_db(sqlite3 *db, fts5_api **ppApi){ |
71 fts5_api *pRet = 0; | |
72 sqlite3_stmt *pStmt = 0; | 72 sqlite3_stmt *pStmt = 0; |
| 73 int rc; |
73 | 74 |
74 if( SQLITE_OK==sqlite3_prepare(db, "SELECT fts5()", -1, &pStmt, 0) | 75 *ppApi = 0; |
75 && SQLITE_ROW==sqlite3_step(pStmt) | 76 rc = sqlite3_prepare(db, "SELECT fts5()", -1, &pStmt, 0); |
76 && sizeof(pRet)==sqlite3_column_bytes(pStmt, 0) | 77 if( rc==SQLITE_OK ){ |
77 ){ | 78 if( SQLITE_ROW==sqlite3_step(pStmt) |
78 memcpy(&pRet, sqlite3_column_blob(pStmt, 0), sizeof(pRet)); | 79 && sizeof(fts5_api*)==sqlite3_column_bytes(pStmt, 0) |
| 80 ){ |
| 81 memcpy(ppApi, sqlite3_column_blob(pStmt, 0), sizeof(fts5_api*)); |
| 82 } |
| 83 rc = sqlite3_finalize(pStmt); |
79 } | 84 } |
80 sqlite3_finalize(pStmt); | 85 |
81 return pRet; | 86 return rc; |
82 } | 87 } |
83 | 88 |
84 | 89 |
85 /* | 90 /* |
86 ** Argument f should be a flag accepted by matchinfo() (a valid character | 91 ** Argument f should be a flag accepted by matchinfo() (a valid character |
87 ** in the string passed as the second argument). If it is not, -1 is | 92 ** in the string passed as the second argument). If it is not, -1 is |
88 ** returned. Otherwise, if f is a valid matchinfo flag, the value returned | 93 ** returned. Otherwise, if f is a valid matchinfo flag, the value returned |
89 ** is the number of 32-bit integers added to the output array if the | 94 ** is the number of 32-bit integers added to the output array if the |
90 ** table has nCol columns and the query nPhrase phrases. | 95 ** table has nCol columns and the query nPhrase phrases. |
91 */ | 96 */ |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 const Fts5ExtensionApi *pApi, | 132 const Fts5ExtensionApi *pApi, |
128 Fts5Context *pFts, | 133 Fts5Context *pFts, |
129 void *pUserData | 134 void *pUserData |
130 ){ | 135 ){ |
131 Fts5PhraseIter iter; | 136 Fts5PhraseIter iter; |
132 int iCol, iOff; | 137 int iCol, iOff; |
133 u32 *aOut = (u32*)pUserData; | 138 u32 *aOut = (u32*)pUserData; |
134 int iPrev = -1; | 139 int iPrev = -1; |
135 | 140 |
136 for(pApi->xPhraseFirst(pFts, 0, &iter, &iCol, &iOff); | 141 for(pApi->xPhraseFirst(pFts, 0, &iter, &iCol, &iOff); |
137 iOff>=0; | 142 iCol>=0; |
138 pApi->xPhraseNext(pFts, &iter, &iCol, &iOff) | 143 pApi->xPhraseNext(pFts, &iter, &iCol, &iOff) |
139 ){ | 144 ){ |
140 aOut[iCol*3+1]++; | 145 aOut[iCol*3+1]++; |
141 if( iCol!=iPrev ) aOut[iCol*3 + 2]++; | 146 if( iCol!=iPrev ) aOut[iCol*3 + 2]++; |
142 iPrev = iCol; | 147 iPrev = iCol; |
143 } | 148 } |
144 | 149 |
145 return SQLITE_OK; | 150 return SQLITE_OK; |
146 } | 151 } |
147 | 152 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 const Fts5ExtensionApi *pApi, | 209 const Fts5ExtensionApi *pApi, |
205 Fts5Context *pFts, | 210 Fts5Context *pFts, |
206 Fts5MatchinfoCtx *p, | 211 Fts5MatchinfoCtx *p, |
207 char f, | 212 char f, |
208 u32 *aOut | 213 u32 *aOut |
209 ){ | 214 ){ |
210 int i; | 215 int i; |
211 int rc = SQLITE_OK; | 216 int rc = SQLITE_OK; |
212 | 217 |
213 switch( f ){ | 218 switch( f ){ |
214 case 'b': | 219 case 'b': { |
| 220 int iPhrase; |
| 221 int nInt = ((p->nCol + 31) / 32) * p->nPhrase; |
| 222 for(i=0; i<nInt; i++) aOut[i] = 0; |
| 223 |
| 224 for(iPhrase=0; iPhrase<p->nPhrase; iPhrase++){ |
| 225 Fts5PhraseIter iter; |
| 226 int iCol; |
| 227 for(pApi->xPhraseFirstColumn(pFts, iPhrase, &iter, &iCol); |
| 228 iCol>=0; |
| 229 pApi->xPhraseNextColumn(pFts, &iter, &iCol) |
| 230 ){ |
| 231 aOut[iPhrase * ((p->nCol+31)/32) + iCol/32] |= ((u32)1 << iCol%32); |
| 232 } |
| 233 } |
| 234 |
| 235 break; |
| 236 } |
| 237 |
215 case 'x': | 238 case 'x': |
216 case 'y': { | 239 case 'y': { |
217 int nMul = (f=='x' ? 3 : 1); | 240 int nMul = (f=='x' ? 3 : 1); |
218 int iPhrase; | 241 int iPhrase; |
219 | 242 |
220 if( f=='b' ){ | 243 for(i=0; i<(p->nCol*p->nPhrase); i++) aOut[i*nMul] = 0; |
221 int nInt = ((p->nCol + 31) / 32) * p->nPhrase; | |
222 for(i=0; i<nInt; i++) aOut[i] = 0; | |
223 }else{ | |
224 for(i=0; i<(p->nCol*p->nPhrase); i++) aOut[i*nMul] = 0; | |
225 } | |
226 | 244 |
227 for(iPhrase=0; iPhrase<p->nPhrase; iPhrase++){ | 245 for(iPhrase=0; iPhrase<p->nPhrase; iPhrase++){ |
228 Fts5PhraseIter iter; | 246 Fts5PhraseIter iter; |
229 int iOff, iCol; | 247 int iOff, iCol; |
230 for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff); | 248 for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff); |
231 iOff>=0; | 249 iOff>=0; |
232 pApi->xPhraseNext(pFts, &iter, &iCol, &iOff) | 250 pApi->xPhraseNext(pFts, &iter, &iCol, &iOff) |
233 ){ | 251 ){ |
234 if( f=='b' ){ | 252 aOut[nMul * (iCol + iPhrase * p->nCol)]++; |
235 aOut[iPhrase * ((p->nCol+31)/32) + iCol/32] |= ((u32)1 << iCol%32); | |
236 }else{ | |
237 aOut[nMul * (iCol + iPhrase * p->nCol)]++; | |
238 } | |
239 } | 253 } |
240 } | 254 } |
241 | 255 |
242 break; | 256 break; |
243 } | 257 } |
244 | 258 |
245 case 'l': { | 259 case 'l': { |
246 for(i=0; rc==SQLITE_OK && i<p->nCol; i++){ | 260 for(i=0; rc==SQLITE_OK && i<p->nCol; i++){ |
247 int nToken; | 261 int nToken; |
248 rc = pApi->xColumnSize(pFts, i, &nToken); | 262 rc = pApi->xColumnSize(pFts, i, &nToken); |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 } | 396 } |
383 } | 397 } |
384 | 398 |
385 int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){ | 399 int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){ |
386 int rc; /* Return code */ | 400 int rc; /* Return code */ |
387 fts5_api *pApi; /* FTS5 API functions */ | 401 fts5_api *pApi; /* FTS5 API functions */ |
388 | 402 |
389 /* Extract the FTS5 API pointer from the database handle. The | 403 /* Extract the FTS5 API pointer from the database handle. The |
390 ** fts5_api_from_db() function above is copied verbatim from the | 404 ** fts5_api_from_db() function above is copied verbatim from the |
391 ** FTS5 documentation. Refer there for details. */ | 405 ** FTS5 documentation. Refer there for details. */ |
392 pApi = fts5_api_from_db(db); | 406 rc = fts5_api_from_db(db, &pApi); |
| 407 if( rc!=SQLITE_OK ) return rc; |
393 | 408 |
394 /* If fts5_api_from_db() returns NULL, then either FTS5 is not registered | 409 /* If fts5_api_from_db() returns NULL, then either FTS5 is not registered |
395 ** with this database handle, or an error (OOM perhaps?) has occurred. | 410 ** with this database handle, or an error (OOM perhaps?) has occurred. |
396 ** | 411 ** |
397 ** Also check that the fts5_api object is version 2 or newer. | 412 ** Also check that the fts5_api object is version 2 or newer. |
398 */ | 413 */ |
399 if( pApi==0 || pApi->iVersion<1 ){ | 414 if( pApi==0 || pApi->iVersion<2 ){ |
400 return SQLITE_ERROR; | 415 return SQLITE_ERROR; |
401 } | 416 } |
402 | 417 |
403 /* Register the implementation of matchinfo() */ | 418 /* Register the implementation of matchinfo() */ |
404 rc = pApi->xCreateFunction(pApi, "matchinfo", 0, fts5MatchinfoFunc, 0); | 419 rc = pApi->xCreateFunction(pApi, "matchinfo", 0, fts5MatchinfoFunc, 0); |
405 | 420 |
406 return rc; | 421 return rc; |
407 } | 422 } |
408 | 423 |
409 #endif /* SQLITE_ENABLE_FTS5 */ | 424 #endif /* SQLITE_ENABLE_FTS5 */ |
410 #endif /* SQLITE_TEST */ | |
411 | 425 |
OLD | NEW |