1
0

fts3_aux.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. /*
  2. ** 2011 Jan 27
  3. **
  4. ** The author disclaims copyright to this source code. In place of
  5. ** a legal notice, here is a blessing:
  6. **
  7. ** May you do good and not evil.
  8. ** May you find forgiveness for yourself and forgive others.
  9. ** May you share freely, never taking more than you give.
  10. **
  11. ******************************************************************************
  12. **
  13. */
  14. #include "fts3Int.h"
  15. #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
  16. #include <string.h>
  17. #include <assert.h>
  18. typedef struct Fts3auxTable Fts3auxTable;
  19. typedef struct Fts3auxCursor Fts3auxCursor;
  20. struct Fts3auxTable {
  21. sqlite3_vtab base; /* Base class used by SQLite core */
  22. Fts3Table *pFts3Tab;
  23. };
  24. struct Fts3auxCursor {
  25. sqlite3_vtab_cursor base; /* Base class used by SQLite core */
  26. Fts3MultiSegReader csr; /* Must be right after "base" */
  27. Fts3SegFilter filter;
  28. char *zStop;
  29. int nStop; /* Byte-length of string zStop */
  30. int iLangid; /* Language id to query */
  31. int isEof; /* True if cursor is at EOF */
  32. sqlite3_int64 iRowid; /* Current rowid */
  33. int iCol; /* Current value of 'col' column */
  34. int nStat; /* Size of aStat[] array */
  35. struct Fts3auxColstats {
  36. sqlite3_int64 nDoc; /* 'documents' values for current csr row */
  37. sqlite3_int64 nOcc; /* 'occurrences' values for current csr row */
  38. } *aStat;
  39. };
  40. /*
  41. ** Schema of the terms table.
  42. */
  43. #define FTS3_AUX_SCHEMA \
  44. "CREATE TABLE x(term, col, documents, occurrences, languageid HIDDEN)"
  45. /*
  46. ** This function does all the work for both the xConnect and xCreate methods.
  47. ** These tables have no persistent representation of their own, so xConnect
  48. ** and xCreate are identical operations.
  49. */
  50. static int fts3auxConnectMethod(
  51. sqlite3 *db, /* Database connection */
  52. void *pUnused, /* Unused */
  53. int argc, /* Number of elements in argv array */
  54. const char * const *argv, /* xCreate/xConnect argument array */
  55. sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */
  56. char **pzErr /* OUT: sqlite3_malloc'd error message */
  57. ){
  58. char const *zDb; /* Name of database (e.g. "main") */
  59. char const *zFts3; /* Name of fts3 table */
  60. int nDb; /* Result of strlen(zDb) */
  61. int nFts3; /* Result of strlen(zFts3) */
  62. int nByte; /* Bytes of space to allocate here */
  63. int rc; /* value returned by declare_vtab() */
  64. Fts3auxTable *p; /* Virtual table object to return */
  65. UNUSED_PARAMETER(pUnused);
  66. /* The user should invoke this in one of two forms:
  67. **
  68. ** CREATE VIRTUAL TABLE xxx USING fts4aux(fts4-table);
  69. ** CREATE VIRTUAL TABLE xxx USING fts4aux(fts4-table-db, fts4-table);
  70. */
  71. if( argc!=4 && argc!=5 ) goto bad_args;
  72. zDb = argv[1];
  73. nDb = (int)strlen(zDb);
  74. if( argc==5 ){
  75. if( nDb==4 && 0==sqlite3_strnicmp("temp", zDb, 4) ){
  76. zDb = argv[3];
  77. nDb = (int)strlen(zDb);
  78. zFts3 = argv[4];
  79. }else{
  80. goto bad_args;
  81. }
  82. }else{
  83. zFts3 = argv[3];
  84. }
  85. nFts3 = (int)strlen(zFts3);
  86. rc = sqlite3_declare_vtab(db, FTS3_AUX_SCHEMA);
  87. if( rc!=SQLITE_OK ) return rc;
  88. nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
  89. p = (Fts3auxTable *)sqlite3_malloc(nByte);
  90. if( !p ) return SQLITE_NOMEM;
  91. memset(p, 0, nByte);
  92. p->pFts3Tab = (Fts3Table *)&p[1];
  93. p->pFts3Tab->zDb = (char *)&p->pFts3Tab[1];
  94. p->pFts3Tab->zName = &p->pFts3Tab->zDb[nDb+1];
  95. p->pFts3Tab->db = db;
  96. p->pFts3Tab->nIndex = 1;
  97. memcpy((char *)p->pFts3Tab->zDb, zDb, nDb);
  98. memcpy((char *)p->pFts3Tab->zName, zFts3, nFts3);
  99. sqlite3Fts3Dequote((char *)p->pFts3Tab->zName);
  100. *ppVtab = (sqlite3_vtab *)p;
  101. return SQLITE_OK;
  102. bad_args:
  103. *pzErr = sqlite3_mprintf("invalid arguments to fts4aux constructor");
  104. return SQLITE_ERROR;
  105. }
  106. /*
  107. ** This function does the work for both the xDisconnect and xDestroy methods.
  108. ** These tables have no persistent representation of their own, so xDisconnect
  109. ** and xDestroy are identical operations.
  110. */
  111. static int fts3auxDisconnectMethod(sqlite3_vtab *pVtab){
  112. Fts3auxTable *p = (Fts3auxTable *)pVtab;
  113. Fts3Table *pFts3 = p->pFts3Tab;
  114. int i;
  115. /* Free any prepared statements held */
  116. for(i=0; i<SizeofArray(pFts3->aStmt); i++){
  117. sqlite3_finalize(pFts3->aStmt[i]);
  118. }
  119. sqlite3_free(pFts3->zSegmentsTbl);
  120. sqlite3_free(p);
  121. return SQLITE_OK;
  122. }
  123. #define FTS4AUX_EQ_CONSTRAINT 1
  124. #define FTS4AUX_GE_CONSTRAINT 2
  125. #define FTS4AUX_LE_CONSTRAINT 4
  126. /*
  127. ** xBestIndex - Analyze a WHERE and ORDER BY clause.
  128. */
  129. static int fts3auxBestIndexMethod(
  130. sqlite3_vtab *pVTab,
  131. sqlite3_index_info *pInfo
  132. ){
  133. int i;
  134. int iEq = -1;
  135. int iGe = -1;
  136. int iLe = -1;
  137. int iLangid = -1;
  138. int iNext = 1; /* Next free argvIndex value */
  139. UNUSED_PARAMETER(pVTab);
  140. /* This vtab delivers always results in "ORDER BY term ASC" order. */
  141. if( pInfo->nOrderBy==1
  142. && pInfo->aOrderBy[0].iColumn==0
  143. && pInfo->aOrderBy[0].desc==0
  144. ){
  145. pInfo->orderByConsumed = 1;
  146. }
  147. /* Search for equality and range constraints on the "term" column.
  148. ** And equality constraints on the hidden "languageid" column. */
  149. for(i=0; i<pInfo->nConstraint; i++){
  150. if( pInfo->aConstraint[i].usable ){
  151. int op = pInfo->aConstraint[i].op;
  152. int iCol = pInfo->aConstraint[i].iColumn;
  153. if( iCol==0 ){
  154. if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i;
  155. if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i;
  156. if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i;
  157. if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i;
  158. if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i;
  159. }
  160. if( iCol==4 ){
  161. if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iLangid = i;
  162. }
  163. }
  164. }
  165. if( iEq>=0 ){
  166. pInfo->idxNum = FTS4AUX_EQ_CONSTRAINT;
  167. pInfo->aConstraintUsage[iEq].argvIndex = iNext++;
  168. pInfo->estimatedCost = 5;
  169. }else{
  170. pInfo->idxNum = 0;
  171. pInfo->estimatedCost = 20000;
  172. if( iGe>=0 ){
  173. pInfo->idxNum += FTS4AUX_GE_CONSTRAINT;
  174. pInfo->aConstraintUsage[iGe].argvIndex = iNext++;
  175. pInfo->estimatedCost /= 2;
  176. }
  177. if( iLe>=0 ){
  178. pInfo->idxNum += FTS4AUX_LE_CONSTRAINT;
  179. pInfo->aConstraintUsage[iLe].argvIndex = iNext++;
  180. pInfo->estimatedCost /= 2;
  181. }
  182. }
  183. if( iLangid>=0 ){
  184. pInfo->aConstraintUsage[iLangid].argvIndex = iNext++;
  185. pInfo->estimatedCost--;
  186. }
  187. return SQLITE_OK;
  188. }
  189. /*
  190. ** xOpen - Open a cursor.
  191. */
  192. static int fts3auxOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
  193. Fts3auxCursor *pCsr; /* Pointer to cursor object to return */
  194. UNUSED_PARAMETER(pVTab);
  195. pCsr = (Fts3auxCursor *)sqlite3_malloc(sizeof(Fts3auxCursor));
  196. if( !pCsr ) return SQLITE_NOMEM;
  197. memset(pCsr, 0, sizeof(Fts3auxCursor));
  198. *ppCsr = (sqlite3_vtab_cursor *)pCsr;
  199. return SQLITE_OK;
  200. }
  201. /*
  202. ** xClose - Close a cursor.
  203. */
  204. static int fts3auxCloseMethod(sqlite3_vtab_cursor *pCursor){
  205. Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab;
  206. Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
  207. sqlite3Fts3SegmentsClose(pFts3);
  208. sqlite3Fts3SegReaderFinish(&pCsr->csr);
  209. sqlite3_free((void *)pCsr->filter.zTerm);
  210. sqlite3_free(pCsr->zStop);
  211. sqlite3_free(pCsr->aStat);
  212. sqlite3_free(pCsr);
  213. return SQLITE_OK;
  214. }
  215. static int fts3auxGrowStatArray(Fts3auxCursor *pCsr, int nSize){
  216. if( nSize>pCsr->nStat ){
  217. struct Fts3auxColstats *aNew;
  218. aNew = (struct Fts3auxColstats *)sqlite3_realloc(pCsr->aStat,
  219. sizeof(struct Fts3auxColstats) * nSize
  220. );
  221. if( aNew==0 ) return SQLITE_NOMEM;
  222. memset(&aNew[pCsr->nStat], 0,
  223. sizeof(struct Fts3auxColstats) * (nSize - pCsr->nStat)
  224. );
  225. pCsr->aStat = aNew;
  226. pCsr->nStat = nSize;
  227. }
  228. return SQLITE_OK;
  229. }
  230. /*
  231. ** xNext - Advance the cursor to the next row, if any.
  232. */
  233. static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){
  234. Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
  235. Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab;
  236. int rc;
  237. /* Increment our pretend rowid value. */
  238. pCsr->iRowid++;
  239. for(pCsr->iCol++; pCsr->iCol<pCsr->nStat; pCsr->iCol++){
  240. if( pCsr->aStat[pCsr->iCol].nDoc>0 ) return SQLITE_OK;
  241. }
  242. rc = sqlite3Fts3SegReaderStep(pFts3, &pCsr->csr);
  243. if( rc==SQLITE_ROW ){
  244. int i = 0;
  245. int nDoclist = pCsr->csr.nDoclist;
  246. char *aDoclist = pCsr->csr.aDoclist;
  247. int iCol;
  248. int eState = 0;
  249. if( pCsr->zStop ){
  250. int n = (pCsr->nStop<pCsr->csr.nTerm) ? pCsr->nStop : pCsr->csr.nTerm;
  251. int mc = memcmp(pCsr->zStop, pCsr->csr.zTerm, n);
  252. if( mc<0 || (mc==0 && pCsr->csr.nTerm>pCsr->nStop) ){
  253. pCsr->isEof = 1;
  254. return SQLITE_OK;
  255. }
  256. }
  257. if( fts3auxGrowStatArray(pCsr, 2) ) return SQLITE_NOMEM;
  258. memset(pCsr->aStat, 0, sizeof(struct Fts3auxColstats) * pCsr->nStat);
  259. iCol = 0;
  260. while( i<nDoclist ){
  261. sqlite3_int64 v = 0;
  262. i += sqlite3Fts3GetVarint(&aDoclist[i], &v);
  263. switch( eState ){
  264. /* State 0. In this state the integer just read was a docid. */
  265. case 0:
  266. pCsr->aStat[0].nDoc++;
  267. eState = 1;
  268. iCol = 0;
  269. break;
  270. /* State 1. In this state we are expecting either a 1, indicating
  271. ** that the following integer will be a column number, or the
  272. ** start of a position list for column 0.
  273. **
  274. ** The only difference between state 1 and state 2 is that if the
  275. ** integer encountered in state 1 is not 0 or 1, then we need to
  276. ** increment the column 0 "nDoc" count for this term.
  277. */
  278. case 1:
  279. assert( iCol==0 );
  280. if( v>1 ){
  281. pCsr->aStat[1].nDoc++;
  282. }
  283. eState = 2;
  284. /* fall through */
  285. case 2:
  286. if( v==0 ){ /* 0x00. Next integer will be a docid. */
  287. eState = 0;
  288. }else if( v==1 ){ /* 0x01. Next integer will be a column number. */
  289. eState = 3;
  290. }else{ /* 2 or greater. A position. */
  291. pCsr->aStat[iCol+1].nOcc++;
  292. pCsr->aStat[0].nOcc++;
  293. }
  294. break;
  295. /* State 3. The integer just read is a column number. */
  296. default: assert( eState==3 );
  297. iCol = (int)v;
  298. if( fts3auxGrowStatArray(pCsr, iCol+2) ) return SQLITE_NOMEM;
  299. pCsr->aStat[iCol+1].nDoc++;
  300. eState = 2;
  301. break;
  302. }
  303. }
  304. pCsr->iCol = 0;
  305. rc = SQLITE_OK;
  306. }else{
  307. pCsr->isEof = 1;
  308. }
  309. return rc;
  310. }
  311. /*
  312. ** xFilter - Initialize a cursor to point at the start of its data.
  313. */
  314. static int fts3auxFilterMethod(
  315. sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
  316. int idxNum, /* Strategy index */
  317. const char *idxStr, /* Unused */
  318. int nVal, /* Number of elements in apVal */
  319. sqlite3_value **apVal /* Arguments for the indexing scheme */
  320. ){
  321. Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
  322. Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab;
  323. int rc;
  324. int isScan = 0;
  325. int iLangVal = 0; /* Language id to query */
  326. int iEq = -1; /* Index of term=? value in apVal */
  327. int iGe = -1; /* Index of term>=? value in apVal */
  328. int iLe = -1; /* Index of term<=? value in apVal */
  329. int iLangid = -1; /* Index of languageid=? value in apVal */
  330. int iNext = 0;
  331. UNUSED_PARAMETER(nVal);
  332. UNUSED_PARAMETER(idxStr);
  333. assert( idxStr==0 );
  334. assert( idxNum==FTS4AUX_EQ_CONSTRAINT || idxNum==0
  335. || idxNum==FTS4AUX_LE_CONSTRAINT || idxNum==FTS4AUX_GE_CONSTRAINT
  336. || idxNum==(FTS4AUX_LE_CONSTRAINT|FTS4AUX_GE_CONSTRAINT)
  337. );
  338. if( idxNum==FTS4AUX_EQ_CONSTRAINT ){
  339. iEq = iNext++;
  340. }else{
  341. isScan = 1;
  342. if( idxNum & FTS4AUX_GE_CONSTRAINT ){
  343. iGe = iNext++;
  344. }
  345. if( idxNum & FTS4AUX_LE_CONSTRAINT ){
  346. iLe = iNext++;
  347. }
  348. }
  349. if( iNext<nVal ){
  350. iLangid = iNext++;
  351. }
  352. /* In case this cursor is being reused, close and zero it. */
  353. testcase(pCsr->filter.zTerm);
  354. sqlite3Fts3SegReaderFinish(&pCsr->csr);
  355. sqlite3_free((void *)pCsr->filter.zTerm);
  356. sqlite3_free(pCsr->aStat);
  357. memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr);
  358. pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
  359. if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN;
  360. if( iEq>=0 || iGe>=0 ){
  361. const unsigned char *zStr = sqlite3_value_text(apVal[0]);
  362. assert( (iEq==0 && iGe==-1) || (iEq==-1 && iGe==0) );
  363. if( zStr ){
  364. pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr);
  365. pCsr->filter.nTerm = sqlite3_value_bytes(apVal[0]);
  366. if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM;
  367. }
  368. }
  369. if( iLe>=0 ){
  370. pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iLe]));
  371. pCsr->nStop = sqlite3_value_bytes(apVal[iLe]);
  372. if( pCsr->zStop==0 ) return SQLITE_NOMEM;
  373. }
  374. if( iLangid>=0 ){
  375. iLangVal = sqlite3_value_int(apVal[iLangid]);
  376. /* If the user specified a negative value for the languageid, use zero
  377. ** instead. This works, as the "languageid=?" constraint will also
  378. ** be tested by the VDBE layer. The test will always be false (since
  379. ** this module will not return a row with a negative languageid), and
  380. ** so the overall query will return zero rows. */
  381. if( iLangVal<0 ) iLangVal = 0;
  382. }
  383. pCsr->iLangid = iLangVal;
  384. rc = sqlite3Fts3SegReaderCursor(pFts3, iLangVal, 0, FTS3_SEGCURSOR_ALL,
  385. pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr
  386. );
  387. if( rc==SQLITE_OK ){
  388. rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter);
  389. }
  390. if( rc==SQLITE_OK ) rc = fts3auxNextMethod(pCursor);
  391. return rc;
  392. }
  393. /*
  394. ** xEof - Return true if the cursor is at EOF, or false otherwise.
  395. */
  396. static int fts3auxEofMethod(sqlite3_vtab_cursor *pCursor){
  397. Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
  398. return pCsr->isEof;
  399. }
  400. /*
  401. ** xColumn - Return a column value.
  402. */
  403. static int fts3auxColumnMethod(
  404. sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
  405. sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
  406. int iCol /* Index of column to read value from */
  407. ){
  408. Fts3auxCursor *p = (Fts3auxCursor *)pCursor;
  409. assert( p->isEof==0 );
  410. switch( iCol ){
  411. case 0: /* term */
  412. sqlite3_result_text(pCtx, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT);
  413. break;
  414. case 1: /* col */
  415. if( p->iCol ){
  416. sqlite3_result_int(pCtx, p->iCol-1);
  417. }else{
  418. sqlite3_result_text(pCtx, "*", -1, SQLITE_STATIC);
  419. }
  420. break;
  421. case 2: /* documents */
  422. sqlite3_result_int64(pCtx, p->aStat[p->iCol].nDoc);
  423. break;
  424. case 3: /* occurrences */
  425. sqlite3_result_int64(pCtx, p->aStat[p->iCol].nOcc);
  426. break;
  427. default: /* languageid */
  428. assert( iCol==4 );
  429. sqlite3_result_int(pCtx, p->iLangid);
  430. break;
  431. }
  432. return SQLITE_OK;
  433. }
  434. /*
  435. ** xRowid - Return the current rowid for the cursor.
  436. */
  437. static int fts3auxRowidMethod(
  438. sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
  439. sqlite_int64 *pRowid /* OUT: Rowid value */
  440. ){
  441. Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
  442. *pRowid = pCsr->iRowid;
  443. return SQLITE_OK;
  444. }
  445. /*
  446. ** Register the fts3aux module with database connection db. Return SQLITE_OK
  447. ** if successful or an error code if sqlite3_create_module() fails.
  448. */
  449. int sqlite3Fts3InitAux(sqlite3 *db){
  450. static const sqlite3_module fts3aux_module = {
  451. 0, /* iVersion */
  452. fts3auxConnectMethod, /* xCreate */
  453. fts3auxConnectMethod, /* xConnect */
  454. fts3auxBestIndexMethod, /* xBestIndex */
  455. fts3auxDisconnectMethod, /* xDisconnect */
  456. fts3auxDisconnectMethod, /* xDestroy */
  457. fts3auxOpenMethod, /* xOpen */
  458. fts3auxCloseMethod, /* xClose */
  459. fts3auxFilterMethod, /* xFilter */
  460. fts3auxNextMethod, /* xNext */
  461. fts3auxEofMethod, /* xEof */
  462. fts3auxColumnMethod, /* xColumn */
  463. fts3auxRowidMethod, /* xRowid */
  464. 0, /* xUpdate */
  465. 0, /* xBegin */
  466. 0, /* xSync */
  467. 0, /* xCommit */
  468. 0, /* xRollback */
  469. 0, /* xFindFunction */
  470. 0, /* xRename */
  471. 0, /* xSavepoint */
  472. 0, /* xRelease */
  473. 0 /* xRollbackTo */
  474. };
  475. int rc; /* Return code */
  476. rc = sqlite3_create_module(db, "fts4aux", &fts3aux_module, 0);
  477. return rc;
  478. }
  479. #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */