fts5.h 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. /*
  2. ** 2014 May 31
  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. ** Interfaces to extend FTS5. Using the interfaces defined in this file,
  14. ** FTS5 may be extended with:
  15. **
  16. ** * custom tokenizers, and
  17. ** * custom auxiliary functions.
  18. */
  19. #ifndef _FTS5_H
  20. #define _FTS5_H
  21. #include "sqlite3.h"
  22. #ifdef __cplusplus
  23. extern "C" {
  24. #endif
  25. /*************************************************************************
  26. ** CUSTOM AUXILIARY FUNCTIONS
  27. **
  28. ** Virtual table implementations may overload SQL functions by implementing
  29. ** the sqlite3_module.xFindFunction() method.
  30. */
  31. typedef struct Fts5ExtensionApi Fts5ExtensionApi;
  32. typedef struct Fts5Context Fts5Context;
  33. typedef struct Fts5PhraseIter Fts5PhraseIter;
  34. typedef void (*fts5_extension_function)(
  35. const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
  36. Fts5Context *pFts, /* First arg to pass to pApi functions */
  37. sqlite3_context *pCtx, /* Context for returning result/error */
  38. int nVal, /* Number of values in apVal[] array */
  39. sqlite3_value **apVal /* Array of trailing arguments */
  40. );
  41. struct Fts5PhraseIter {
  42. const unsigned char *a;
  43. const unsigned char *b;
  44. };
  45. /*
  46. ** EXTENSION API FUNCTIONS
  47. **
  48. ** xUserData(pFts):
  49. ** Return a copy of the context pointer the extension function was
  50. ** registered with.
  51. **
  52. ** xColumnTotalSize(pFts, iCol, pnToken):
  53. ** If parameter iCol is less than zero, set output variable *pnToken
  54. ** to the total number of tokens in the FTS5 table. Or, if iCol is
  55. ** non-negative but less than the number of columns in the table, return
  56. ** the total number of tokens in column iCol, considering all rows in
  57. ** the FTS5 table.
  58. **
  59. ** If parameter iCol is greater than or equal to the number of columns
  60. ** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
  61. ** an OOM condition or IO error), an appropriate SQLite error code is
  62. ** returned.
  63. **
  64. ** xColumnCount(pFts):
  65. ** Return the number of columns in the table.
  66. **
  67. ** xColumnSize(pFts, iCol, pnToken):
  68. ** If parameter iCol is less than zero, set output variable *pnToken
  69. ** to the total number of tokens in the current row. Or, if iCol is
  70. ** non-negative but less than the number of columns in the table, set
  71. ** *pnToken to the number of tokens in column iCol of the current row.
  72. **
  73. ** If parameter iCol is greater than or equal to the number of columns
  74. ** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
  75. ** an OOM condition or IO error), an appropriate SQLite error code is
  76. ** returned.
  77. **
  78. ** This function may be quite inefficient if used with an FTS5 table
  79. ** created with the "columnsize=0" option.
  80. **
  81. ** xColumnText:
  82. ** This function attempts to retrieve the text of column iCol of the
  83. ** current document. If successful, (*pz) is set to point to a buffer
  84. ** containing the text in utf-8 encoding, (*pn) is set to the size in bytes
  85. ** (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
  86. ** if an error occurs, an SQLite error code is returned and the final values
  87. ** of (*pz) and (*pn) are undefined.
  88. **
  89. ** xPhraseCount:
  90. ** Returns the number of phrases in the current query expression.
  91. **
  92. ** xPhraseSize:
  93. ** Returns the number of tokens in phrase iPhrase of the query. Phrases
  94. ** are numbered starting from zero.
  95. **
  96. ** xInstCount:
  97. ** Set *pnInst to the total number of occurrences of all phrases within
  98. ** the query within the current row. Return SQLITE_OK if successful, or
  99. ** an error code (i.e. SQLITE_NOMEM) if an error occurs.
  100. **
  101. ** This API can be quite slow if used with an FTS5 table created with the
  102. ** "detail=none" or "detail=column" option. If the FTS5 table is created
  103. ** with either "detail=none" or "detail=column" and "content=" option
  104. ** (i.e. if it is a contentless table), then this API always returns 0.
  105. **
  106. ** xInst:
  107. ** Query for the details of phrase match iIdx within the current row.
  108. ** Phrase matches are numbered starting from zero, so the iIdx argument
  109. ** should be greater than or equal to zero and smaller than the value
  110. ** output by xInstCount().
  111. **
  112. ** Usually, output parameter *piPhrase is set to the phrase number, *piCol
  113. ** to the column in which it occurs and *piOff the token offset of the
  114. ** first token of the phrase. The exception is if the table was created
  115. ** with the offsets=0 option specified. In this case *piOff is always
  116. ** set to -1.
  117. **
  118. ** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
  119. ** if an error occurs.
  120. **
  121. ** This API can be quite slow if used with an FTS5 table created with the
  122. ** "detail=none" or "detail=column" option.
  123. **
  124. ** xRowid:
  125. ** Returns the rowid of the current row.
  126. **
  127. ** xTokenize:
  128. ** Tokenize text using the tokenizer belonging to the FTS5 table.
  129. **
  130. ** xQueryPhrase(pFts5, iPhrase, pUserData, xCallback):
  131. ** This API function is used to query the FTS table for phrase iPhrase
  132. ** of the current query. Specifically, a query equivalent to:
  133. **
  134. ** ... FROM ftstable WHERE ftstable MATCH $p ORDER BY rowid
  135. **
  136. ** with $p set to a phrase equivalent to the phrase iPhrase of the
  137. ** current query is executed. Any column filter that applies to
  138. ** phrase iPhrase of the current query is included in $p. For each
  139. ** row visited, the callback function passed as the fourth argument
  140. ** is invoked. The context and API objects passed to the callback
  141. ** function may be used to access the properties of each matched row.
  142. ** Invoking Api.xUserData() returns a copy of the pointer passed as
  143. ** the third argument to pUserData.
  144. **
  145. ** If the callback function returns any value other than SQLITE_OK, the
  146. ** query is abandoned and the xQueryPhrase function returns immediately.
  147. ** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK.
  148. ** Otherwise, the error code is propagated upwards.
  149. **
  150. ** If the query runs to completion without incident, SQLITE_OK is returned.
  151. ** Or, if some error occurs before the query completes or is aborted by
  152. ** the callback, an SQLite error code is returned.
  153. **
  154. **
  155. ** xSetAuxdata(pFts5, pAux, xDelete)
  156. **
  157. ** Save the pointer passed as the second argument as the extension functions
  158. ** "auxiliary data". The pointer may then be retrieved by the current or any
  159. ** future invocation of the same fts5 extension function made as part of
  160. ** of the same MATCH query using the xGetAuxdata() API.
  161. **
  162. ** Each extension function is allocated a single auxiliary data slot for
  163. ** each FTS query (MATCH expression). If the extension function is invoked
  164. ** more than once for a single FTS query, then all invocations share a
  165. ** single auxiliary data context.
  166. **
  167. ** If there is already an auxiliary data pointer when this function is
  168. ** invoked, then it is replaced by the new pointer. If an xDelete callback
  169. ** was specified along with the original pointer, it is invoked at this
  170. ** point.
  171. **
  172. ** The xDelete callback, if one is specified, is also invoked on the
  173. ** auxiliary data pointer after the FTS5 query has finished.
  174. **
  175. ** If an error (e.g. an OOM condition) occurs within this function, an
  176. ** the auxiliary data is set to NULL and an error code returned. If the
  177. ** xDelete parameter was not NULL, it is invoked on the auxiliary data
  178. ** pointer before returning.
  179. **
  180. **
  181. ** xGetAuxdata(pFts5, bClear)
  182. **
  183. ** Returns the current auxiliary data pointer for the fts5 extension
  184. ** function. See the xSetAuxdata() method for details.
  185. **
  186. ** If the bClear argument is non-zero, then the auxiliary data is cleared
  187. ** (set to NULL) before this function returns. In this case the xDelete,
  188. ** if any, is not invoked.
  189. **
  190. **
  191. ** xRowCount(pFts5, pnRow)
  192. **
  193. ** This function is used to retrieve the total number of rows in the table.
  194. ** In other words, the same value that would be returned by:
  195. **
  196. ** SELECT count(*) FROM ftstable;
  197. **
  198. ** xPhraseFirst()
  199. ** This function is used, along with type Fts5PhraseIter and the xPhraseNext
  200. ** method, to iterate through all instances of a single query phrase within
  201. ** the current row. This is the same information as is accessible via the
  202. ** xInstCount/xInst APIs. While the xInstCount/xInst APIs are more convenient
  203. ** to use, this API may be faster under some circumstances. To iterate
  204. ** through instances of phrase iPhrase, use the following code:
  205. **
  206. ** Fts5PhraseIter iter;
  207. ** int iCol, iOff;
  208. ** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff);
  209. ** iCol>=0;
  210. ** pApi->xPhraseNext(pFts, &iter, &iCol, &iOff)
  211. ** ){
  212. ** // An instance of phrase iPhrase at offset iOff of column iCol
  213. ** }
  214. **
  215. ** The Fts5PhraseIter structure is defined above. Applications should not
  216. ** modify this structure directly - it should only be used as shown above
  217. ** with the xPhraseFirst() and xPhraseNext() API methods (and by
  218. ** xPhraseFirstColumn() and xPhraseNextColumn() as illustrated below).
  219. **
  220. ** This API can be quite slow if used with an FTS5 table created with the
  221. ** "detail=none" or "detail=column" option. If the FTS5 table is created
  222. ** with either "detail=none" or "detail=column" and "content=" option
  223. ** (i.e. if it is a contentless table), then this API always iterates
  224. ** through an empty set (all calls to xPhraseFirst() set iCol to -1).
  225. **
  226. ** xPhraseNext()
  227. ** See xPhraseFirst above.
  228. **
  229. ** xPhraseFirstColumn()
  230. ** This function and xPhraseNextColumn() are similar to the xPhraseFirst()
  231. ** and xPhraseNext() APIs described above. The difference is that instead
  232. ** of iterating through all instances of a phrase in the current row, these
  233. ** APIs are used to iterate through the set of columns in the current row
  234. ** that contain one or more instances of a specified phrase. For example:
  235. **
  236. ** Fts5PhraseIter iter;
  237. ** int iCol;
  238. ** for(pApi->xPhraseFirstColumn(pFts, iPhrase, &iter, &iCol);
  239. ** iCol>=0;
  240. ** pApi->xPhraseNextColumn(pFts, &iter, &iCol)
  241. ** ){
  242. ** // Column iCol contains at least one instance of phrase iPhrase
  243. ** }
  244. **
  245. ** This API can be quite slow if used with an FTS5 table created with the
  246. ** "detail=none" option. If the FTS5 table is created with either
  247. ** "detail=none" "content=" option (i.e. if it is a contentless table),
  248. ** then this API always iterates through an empty set (all calls to
  249. ** xPhraseFirstColumn() set iCol to -1).
  250. **
  251. ** The information accessed using this API and its companion
  252. ** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext
  253. ** (or xInst/xInstCount). The chief advantage of this API is that it is
  254. ** significantly more efficient than those alternatives when used with
  255. ** "detail=column" tables.
  256. **
  257. ** xPhraseNextColumn()
  258. ** See xPhraseFirstColumn above.
  259. */
  260. struct Fts5ExtensionApi {
  261. int iVersion; /* Currently always set to 3 */
  262. void *(*xUserData)(Fts5Context*);
  263. int (*xColumnCount)(Fts5Context*);
  264. int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
  265. int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken);
  266. int (*xTokenize)(Fts5Context*,
  267. const char *pText, int nText, /* Text to tokenize */
  268. void *pCtx, /* Context passed to xToken() */
  269. int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
  270. );
  271. int (*xPhraseCount)(Fts5Context*);
  272. int (*xPhraseSize)(Fts5Context*, int iPhrase);
  273. int (*xInstCount)(Fts5Context*, int *pnInst);
  274. int (*xInst)(Fts5Context*, int iIdx, int *piPhrase, int *piCol, int *piOff);
  275. sqlite3_int64 (*xRowid)(Fts5Context*);
  276. int (*xColumnText)(Fts5Context*, int iCol, const char **pz, int *pn);
  277. int (*xColumnSize)(Fts5Context*, int iCol, int *pnToken);
  278. int (*xQueryPhrase)(Fts5Context*, int iPhrase, void *pUserData,
  279. int(*)(const Fts5ExtensionApi*,Fts5Context*,void*)
  280. );
  281. int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*));
  282. void *(*xGetAuxdata)(Fts5Context*, int bClear);
  283. int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
  284. void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
  285. int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
  286. void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
  287. };
  288. /*
  289. ** CUSTOM AUXILIARY FUNCTIONS
  290. *************************************************************************/
  291. /*************************************************************************
  292. ** CUSTOM TOKENIZERS
  293. **
  294. ** Applications may also register custom tokenizer types. A tokenizer
  295. ** is registered by providing fts5 with a populated instance of the
  296. ** following structure. All structure methods must be defined, setting
  297. ** any member of the fts5_tokenizer struct to NULL leads to undefined
  298. ** behaviour. The structure methods are expected to function as follows:
  299. **
  300. ** xCreate:
  301. ** This function is used to allocate and initialize a tokenizer instance.
  302. ** A tokenizer instance is required to actually tokenize text.
  303. **
  304. ** The first argument passed to this function is a copy of the (void*)
  305. ** pointer provided by the application when the fts5_tokenizer object
  306. ** was registered with FTS5 (the third argument to xCreateTokenizer()).
  307. ** The second and third arguments are an array of nul-terminated strings
  308. ** containing the tokenizer arguments, if any, specified following the
  309. ** tokenizer name as part of the CREATE VIRTUAL TABLE statement used
  310. ** to create the FTS5 table.
  311. **
  312. ** The final argument is an output variable. If successful, (*ppOut)
  313. ** should be set to point to the new tokenizer handle and SQLITE_OK
  314. ** returned. If an error occurs, some value other than SQLITE_OK should
  315. ** be returned. In this case, fts5 assumes that the final value of *ppOut
  316. ** is undefined.
  317. **
  318. ** xDelete:
  319. ** This function is invoked to delete a tokenizer handle previously
  320. ** allocated using xCreate(). Fts5 guarantees that this function will
  321. ** be invoked exactly once for each successful call to xCreate().
  322. **
  323. ** xTokenize:
  324. ** This function is expected to tokenize the nText byte string indicated
  325. ** by argument pText. pText may or may not be nul-terminated. The first
  326. ** argument passed to this function is a pointer to an Fts5Tokenizer object
  327. ** returned by an earlier call to xCreate().
  328. **
  329. ** The second argument indicates the reason that FTS5 is requesting
  330. ** tokenization of the supplied text. This is always one of the following
  331. ** four values:
  332. **
  333. ** <ul><li> <b>FTS5_TOKENIZE_DOCUMENT</b> - A document is being inserted into
  334. ** or removed from the FTS table. The tokenizer is being invoked to
  335. ** determine the set of tokens to add to (or delete from) the
  336. ** FTS index.
  337. **
  338. ** <li> <b>FTS5_TOKENIZE_QUERY</b> - A MATCH query is being executed
  339. ** against the FTS index. The tokenizer is being called to tokenize
  340. ** a bareword or quoted string specified as part of the query.
  341. **
  342. ** <li> <b>(FTS5_TOKENIZE_QUERY | FTS5_TOKENIZE_PREFIX)</b> - Same as
  343. ** FTS5_TOKENIZE_QUERY, except that the bareword or quoted string is
  344. ** followed by a "*" character, indicating that the last token
  345. ** returned by the tokenizer will be treated as a token prefix.
  346. **
  347. ** <li> <b>FTS5_TOKENIZE_AUX</b> - The tokenizer is being invoked to
  348. ** satisfy an fts5_api.xTokenize() request made by an auxiliary
  349. ** function. Or an fts5_api.xColumnSize() request made by the same
  350. ** on a columnsize=0 database.
  351. ** </ul>
  352. **
  353. ** For each token in the input string, the supplied callback xToken() must
  354. ** be invoked. The first argument to it should be a copy of the pointer
  355. ** passed as the second argument to xTokenize(). The third and fourth
  356. ** arguments are a pointer to a buffer containing the token text, and the
  357. ** size of the token in bytes. The 4th and 5th arguments are the byte offsets
  358. ** of the first byte of and first byte immediately following the text from
  359. ** which the token is derived within the input.
  360. **
  361. ** The second argument passed to the xToken() callback ("tflags") should
  362. ** normally be set to 0. The exception is if the tokenizer supports
  363. ** synonyms. In this case see the discussion below for details.
  364. **
  365. ** FTS5 assumes the xToken() callback is invoked for each token in the
  366. ** order that they occur within the input text.
  367. **
  368. ** If an xToken() callback returns any value other than SQLITE_OK, then
  369. ** the tokenization should be abandoned and the xTokenize() method should
  370. ** immediately return a copy of the xToken() return value. Or, if the
  371. ** input buffer is exhausted, xTokenize() should return SQLITE_OK. Finally,
  372. ** if an error occurs with the xTokenize() implementation itself, it
  373. ** may abandon the tokenization and return any error code other than
  374. ** SQLITE_OK or SQLITE_DONE.
  375. **
  376. ** SYNONYM SUPPORT
  377. **
  378. ** Custom tokenizers may also support synonyms. Consider a case in which a
  379. ** user wishes to query for a phrase such as "first place". Using the
  380. ** built-in tokenizers, the FTS5 query 'first + place' will match instances
  381. ** of "first place" within the document set, but not alternative forms
  382. ** such as "1st place". In some applications, it would be better to match
  383. ** all instances of "first place" or "1st place" regardless of which form
  384. ** the user specified in the MATCH query text.
  385. **
  386. ** There are several ways to approach this in FTS5:
  387. **
  388. ** <ol><li> By mapping all synonyms to a single token. In this case, the
  389. ** In the above example, this means that the tokenizer returns the
  390. ** same token for inputs "first" and "1st". Say that token is in
  391. ** fact "first", so that when the user inserts the document "I won
  392. ** 1st place" entries are added to the index for tokens "i", "won",
  393. ** "first" and "place". If the user then queries for '1st + place',
  394. ** the tokenizer substitutes "first" for "1st" and the query works
  395. ** as expected.
  396. **
  397. ** <li> By adding multiple synonyms for a single term to the FTS index.
  398. ** In this case, when tokenizing query text, the tokenizer may
  399. ** provide multiple synonyms for a single term within the document.
  400. ** FTS5 then queries the index for each synonym individually. For
  401. ** example, faced with the query:
  402. **
  403. ** <codeblock>
  404. ** ... MATCH 'first place'</codeblock>
  405. **
  406. ** the tokenizer offers both "1st" and "first" as synonyms for the
  407. ** first token in the MATCH query and FTS5 effectively runs a query
  408. ** similar to:
  409. **
  410. ** <codeblock>
  411. ** ... MATCH '(first OR 1st) place'</codeblock>
  412. **
  413. ** except that, for the purposes of auxiliary functions, the query
  414. ** still appears to contain just two phrases - "(first OR 1st)"
  415. ** being treated as a single phrase.
  416. **
  417. ** <li> By adding multiple synonyms for a single term to the FTS index.
  418. ** Using this method, when tokenizing document text, the tokenizer
  419. ** provides multiple synonyms for each token. So that when a
  420. ** document such as "I won first place" is tokenized, entries are
  421. ** added to the FTS index for "i", "won", "first", "1st" and
  422. ** "place".
  423. **
  424. ** This way, even if the tokenizer does not provide synonyms
  425. ** when tokenizing query text (it should not - to do would be
  426. ** inefficient), it doesn't matter if the user queries for
  427. ** 'first + place' or '1st + place', as there are entires in the
  428. ** FTS index corresponding to both forms of the first token.
  429. ** </ol>
  430. **
  431. ** Whether it is parsing document or query text, any call to xToken that
  432. ** specifies a <i>tflags</i> argument with the FTS5_TOKEN_COLOCATED bit
  433. ** is considered to supply a synonym for the previous token. For example,
  434. ** when parsing the document "I won first place", a tokenizer that supports
  435. ** synonyms would call xToken() 5 times, as follows:
  436. **
  437. ** <codeblock>
  438. ** xToken(pCtx, 0, "i", 1, 0, 1);
  439. ** xToken(pCtx, 0, "won", 3, 2, 5);
  440. ** xToken(pCtx, 0, "first", 5, 6, 11);
  441. ** xToken(pCtx, FTS5_TOKEN_COLOCATED, "1st", 3, 6, 11);
  442. ** xToken(pCtx, 0, "place", 5, 12, 17);
  443. **</codeblock>
  444. **
  445. ** It is an error to specify the FTS5_TOKEN_COLOCATED flag the first time
  446. ** xToken() is called. Multiple synonyms may be specified for a single token
  447. ** by making multiple calls to xToken(FTS5_TOKEN_COLOCATED) in sequence.
  448. ** There is no limit to the number of synonyms that may be provided for a
  449. ** single token.
  450. **
  451. ** In many cases, method (1) above is the best approach. It does not add
  452. ** extra data to the FTS index or require FTS5 to query for multiple terms,
  453. ** so it is efficient in terms of disk space and query speed. However, it
  454. ** does not support prefix queries very well. If, as suggested above, the
  455. ** token "first" is subsituted for "1st" by the tokenizer, then the query:
  456. **
  457. ** <codeblock>
  458. ** ... MATCH '1s*'</codeblock>
  459. **
  460. ** will not match documents that contain the token "1st" (as the tokenizer
  461. ** will probably not map "1s" to any prefix of "first").
  462. **
  463. ** For full prefix support, method (3) may be preferred. In this case,
  464. ** because the index contains entries for both "first" and "1st", prefix
  465. ** queries such as 'fi*' or '1s*' will match correctly. However, because
  466. ** extra entries are added to the FTS index, this method uses more space
  467. ** within the database.
  468. **
  469. ** Method (2) offers a midpoint between (1) and (3). Using this method,
  470. ** a query such as '1s*' will match documents that contain the literal
  471. ** token "1st", but not "first" (assuming the tokenizer is not able to
  472. ** provide synonyms for prefixes). However, a non-prefix query like '1st'
  473. ** will match against "1st" and "first". This method does not require
  474. ** extra disk space, as no extra entries are added to the FTS index.
  475. ** On the other hand, it may require more CPU cycles to run MATCH queries,
  476. ** as separate queries of the FTS index are required for each synonym.
  477. **
  478. ** When using methods (2) or (3), it is important that the tokenizer only
  479. ** provide synonyms when tokenizing document text (method (2)) or query
  480. ** text (method (3)), not both. Doing so will not cause any errors, but is
  481. ** inefficient.
  482. */
  483. typedef struct Fts5Tokenizer Fts5Tokenizer;
  484. typedef struct fts5_tokenizer fts5_tokenizer;
  485. struct fts5_tokenizer {
  486. int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
  487. void (*xDelete)(Fts5Tokenizer*);
  488. int (*xTokenize)(Fts5Tokenizer*,
  489. void *pCtx,
  490. int flags, /* Mask of FTS5_TOKENIZE_* flags */
  491. const char *pText, int nText,
  492. int (*xToken)(
  493. void *pCtx, /* Copy of 2nd argument to xTokenize() */
  494. int tflags, /* Mask of FTS5_TOKEN_* flags */
  495. const char *pToken, /* Pointer to buffer containing token */
  496. int nToken, /* Size of token in bytes */
  497. int iStart, /* Byte offset of token within input text */
  498. int iEnd /* Byte offset of end of token within input text */
  499. )
  500. );
  501. };
  502. /* Flags that may be passed as the third argument to xTokenize() */
  503. #define FTS5_TOKENIZE_QUERY 0x0001
  504. #define FTS5_TOKENIZE_PREFIX 0x0002
  505. #define FTS5_TOKENIZE_DOCUMENT 0x0004
  506. #define FTS5_TOKENIZE_AUX 0x0008
  507. /* Flags that may be passed by the tokenizer implementation back to FTS5
  508. ** as the third argument to the supplied xToken callback. */
  509. #define FTS5_TOKEN_COLOCATED 0x0001 /* Same position as prev. token */
  510. /*
  511. ** END OF CUSTOM TOKENIZERS
  512. *************************************************************************/
  513. /*************************************************************************
  514. ** FTS5 EXTENSION REGISTRATION API
  515. */
  516. typedef struct fts5_api fts5_api;
  517. struct fts5_api {
  518. int iVersion; /* Currently always set to 2 */
  519. /* Create a new tokenizer */
  520. int (*xCreateTokenizer)(
  521. fts5_api *pApi,
  522. const char *zName,
  523. void *pContext,
  524. fts5_tokenizer *pTokenizer,
  525. void (*xDestroy)(void*)
  526. );
  527. /* Find an existing tokenizer */
  528. int (*xFindTokenizer)(
  529. fts5_api *pApi,
  530. const char *zName,
  531. void **ppContext,
  532. fts5_tokenizer *pTokenizer
  533. );
  534. /* Create a new auxiliary function */
  535. int (*xCreateFunction)(
  536. fts5_api *pApi,
  537. const char *zName,
  538. void *pContext,
  539. fts5_extension_function xFunction,
  540. void (*xDestroy)(void*)
  541. );
  542. };
  543. /*
  544. ** END OF REGISTRATION API
  545. *************************************************************************/
  546. #ifdef __cplusplus
  547. } /* end of the 'extern "C"' block */
  548. #endif
  549. #endif /* _FTS5_H */