|
|
@@ -111,9 +111,9 @@ extern "C" {
|
|
|
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
|
|
** [sqlite_version()] and [sqlite_source_id()].
|
|
|
*/
|
|
|
-#define SQLITE_VERSION "3.8.12"
|
|
|
-#define SQLITE_VERSION_NUMBER 3008012
|
|
|
-#define SQLITE_SOURCE_ID "2015-09-17 17:21:09 6713e35b8a8c997aa2717e86ce6dcd63bb993477"
|
|
|
+#define SQLITE_VERSION "3.10.0"
|
|
|
+#define SQLITE_VERSION_NUMBER 3010000
|
|
|
+#define SQLITE_SOURCE_ID "2015-11-15 11:13:49 791761ebac26c82ab67bdf867117ec5b5d8b20b0"
|
|
|
|
|
|
/*
|
|
|
** CAPI3REF: Run-Time Library Version Numbers
|
|
|
@@ -488,6 +488,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_exec(
|
|
|
#define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8))
|
|
|
#define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8))
|
|
|
#define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8))
|
|
|
+#define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8))
|
|
|
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
|
|
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
|
|
#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
|
|
|
@@ -1610,29 +1611,34 @@ struct sqlite3_mem_methods {
|
|
|
** </dd>
|
|
|
**
|
|
|
** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
|
|
|
-** <dd> ^The SQLITE_CONFIG_PAGECACHE option specifies a static memory buffer
|
|
|
+** <dd> ^The SQLITE_CONFIG_PAGECACHE option specifies a memory pool
|
|
|
** that SQLite can use for the database page cache with the default page
|
|
|
** cache implementation.
|
|
|
-** This configuration should not be used if an application-define page
|
|
|
-** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2]
|
|
|
-** configuration option.
|
|
|
+** This configuration option is a no-op if an application-define page
|
|
|
+** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2].
|
|
|
** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to
|
|
|
-** 8-byte aligned
|
|
|
-** memory, the size of each page buffer (sz), and the number of pages (N).
|
|
|
+** 8-byte aligned memory (pMem), the size of each page cache line (sz),
|
|
|
+** and the number of cache lines (N).
|
|
|
** The sz argument should be the size of the largest database page
|
|
|
** (a power of two between 512 and 65536) plus some extra bytes for each
|
|
|
** page header. ^The number of extra bytes needed by the page header
|
|
|
-** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option
|
|
|
-** to [sqlite3_config()].
|
|
|
+** can be determined using [SQLITE_CONFIG_PCACHE_HDRSZ].
|
|
|
** ^It is harmless, apart from the wasted memory,
|
|
|
-** for the sz parameter to be larger than necessary. The first
|
|
|
-** argument should pointer to an 8-byte aligned block of memory that
|
|
|
-** is at least sz*N bytes of memory, otherwise subsequent behavior is
|
|
|
-** undefined.
|
|
|
-** ^SQLite will use the memory provided by the first argument to satisfy its
|
|
|
-** memory needs for the first N pages that it adds to cache. ^If additional
|
|
|
-** page cache memory is needed beyond what is provided by this option, then
|
|
|
-** SQLite goes to [sqlite3_malloc()] for the additional storage space.</dd>
|
|
|
+** for the sz parameter to be larger than necessary. The pMem
|
|
|
+** argument must be either a NULL pointer or a pointer to an 8-byte
|
|
|
+** aligned block of memory of at least sz*N bytes, otherwise
|
|
|
+** subsequent behavior is undefined.
|
|
|
+** ^When pMem is not NULL, SQLite will strive to use the memory provided
|
|
|
+** to satisfy page cache needs, falling back to [sqlite3_malloc()] if
|
|
|
+** a page cache line is larger than sz bytes or if all of the pMem buffer
|
|
|
+** is exhausted.
|
|
|
+** ^If pMem is NULL and N is non-zero, then each database connection
|
|
|
+** does an initial bulk allocation for page cache memory
|
|
|
+** from [sqlite3_malloc()] sufficient for N cache lines if N is positive or
|
|
|
+** of -1024*N bytes if N is negative, . ^If additional
|
|
|
+** page cache memory is needed beyond what is provided by the initial
|
|
|
+** allocation, then SQLite goes to [sqlite3_malloc()] separately for each
|
|
|
+** additional cache line. </dd>
|
|
|
**
|
|
|
** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt>
|
|
|
** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer
|
|
|
@@ -3662,7 +3668,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt*,
|
|
|
**
|
|
|
** See also: [sqlite3_bind_blob|sqlite3_bind()],
|
|
|
** [sqlite3_bind_parameter_count()], and
|
|
|
-** [sqlite3_bind_parameter_index()].
|
|
|
+** [sqlite3_bind_parameter_name()].
|
|
|
*/
|
|
|
SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
|
|
|
|
|
|
@@ -4392,7 +4398,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value*);
|
|
|
SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value*);
|
|
|
|
|
|
/*
|
|
|
-** CAPI3REF: Obtaining SQL Values
|
|
|
+** CAPI3REF: Finding The Subtype Of SQL Values
|
|
|
** METHOD: sqlite3_value
|
|
|
**
|
|
|
** The sqlite3_value_subtype(V) function returns the subtype for
|
|
|
@@ -5671,13 +5677,31 @@ struct sqlite3_module {
|
|
|
** ^The estimatedRows value is an estimate of the number of rows that
|
|
|
** will be returned by the strategy.
|
|
|
**
|
|
|
+** The xBestIndex method may optionally populate the idxFlags field with a
|
|
|
+** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag -
|
|
|
+** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite
|
|
|
+** assumes that the strategy may visit at most one row.
|
|
|
+**
|
|
|
+** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then
|
|
|
+** SQLite also assumes that if a call to the xUpdate() method is made as
|
|
|
+** part of the same statement to delete or update a virtual table row and the
|
|
|
+** implementation returns SQLITE_CONSTRAINT, then there is no need to rollback
|
|
|
+** any database changes. In other words, if the xUpdate() returns
|
|
|
+** SQLITE_CONSTRAINT, the database contents must be exactly as they were
|
|
|
+** before xUpdate was called. By contrast, if SQLITE_INDEX_SCAN_UNIQUE is not
|
|
|
+** set and xUpdate returns SQLITE_CONSTRAINT, any database changes made by
|
|
|
+** the xUpdate method are automatically rolled back by SQLite.
|
|
|
+**
|
|
|
** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info
|
|
|
** structure for SQLite version 3.8.2. If a virtual table extension is
|
|
|
** used with an SQLite version earlier than 3.8.2, the results of attempting
|
|
|
** to read or write the estimatedRows field are undefined (but are likely
|
|
|
** to included crashing the application). The estimatedRows field should
|
|
|
** therefore only be used if [sqlite3_libversion_number()] returns a
|
|
|
-** value greater than or equal to 3008002.
|
|
|
+** value greater than or equal to 3008002. Similarly, the idxFlags field
|
|
|
+** was added for version 3.9.0. It may therefore only be used if
|
|
|
+** sqlite3_libversion_number() returns a value greater than or equal to
|
|
|
+** 3009000.
|
|
|
*/
|
|
|
struct sqlite3_index_info {
|
|
|
/* Inputs */
|
|
|
@@ -5705,8 +5729,15 @@ struct sqlite3_index_info {
|
|
|
sqlite_double estimatedCost; /* Estimated cost of using this index */
|
|
|
/* Fields below are only available in SQLite 3.8.2 and later */
|
|
|
sqlite3_int64 estimatedRows; /* Estimated number of rows returned */
|
|
|
+ /* Fields below are only available in SQLite 3.9.0 and later */
|
|
|
+ int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */
|
|
|
};
|
|
|
|
|
|
+/*
|
|
|
+** CAPI3REF: Virtual Table Scan Flags
|
|
|
+*/
|
|
|
+#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */
|
|
|
+
|
|
|
/*
|
|
|
** CAPI3REF: Virtual Table Constraint Operator Codes
|
|
|
**
|
|
|
@@ -6584,7 +6615,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_status64(
|
|
|
** The value written into the *pCurrent parameter is undefined.</dd>)^
|
|
|
**
|
|
|
** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
|
|
|
-** <dd>This parameter records the deepest parser stack. It is only
|
|
|
+** <dd>The *pHighwater parameter records the deepest parser stack.
|
|
|
+** The *pCurrent value is undefined. The *pHighwater value is only
|
|
|
** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>)^
|
|
|
** </dl>
|
|
|
**
|
|
|
@@ -7802,6 +7834,35 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus(
|
|
|
*/
|
|
|
SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
|
|
|
|
|
|
+/*
|
|
|
+** CAPI3REF: Flush caches to disk mid-transaction
|
|
|
+**
|
|
|
+** If a write-transaction is open when this function is called, any dirty
|
|
|
+** pages in the pager-cache that are not currently in use are written out
|
|
|
+** to disk. A dirty page may be in use if a database cursor created by an
|
|
|
+** active SQL statement is reading from it, or if it is page 1 of a database
|
|
|
+** file (page 1 is always "in use"). Dirty pages are flushed for all
|
|
|
+** databases - "main", "temp" and any attached databases.
|
|
|
+**
|
|
|
+** If this function needs to obtain extra database locks before dirty pages
|
|
|
+** can be flushed to disk, it does so. If said locks cannot be obtained
|
|
|
+** immediately and there is a busy-handler callback configured, it is invoked
|
|
|
+** in the usual manner. If the required lock still cannot be obtained, then
|
|
|
+** the database is skipped and an attempt made to flush any dirty pages
|
|
|
+** belonging to the next (if any) database. If any databases are skipped
|
|
|
+** because locks cannot be obtained, but no other error occurs, this
|
|
|
+** function returns SQLITE_BUSY.
|
|
|
+**
|
|
|
+** If any other error occurs while flushing dirty pages to disk (for
|
|
|
+** example an IO error or out-of-memory condition), then processing is
|
|
|
+** abandoned and an SQLite error code returned to the caller immediately.
|
|
|
+**
|
|
|
+** Otherwise, if no error occurs, SQLITE_OK is returned.
|
|
|
+**
|
|
|
+** This function does not set the database handle error code or message
|
|
|
+** returned by the sqlite3_errcode() and sqlite3_errmsg() functions.
|
|
|
+*/
|
|
|
+SQLITE_API int SQLITE_STDCALL sqlite3_db_cacheflush(sqlite3*);
|
|
|
|
|
|
/*
|
|
|
** Undo the hack that converts floating point types to integer for
|
|
|
@@ -7933,3 +7994,523 @@ struct sqlite3_rtree_query_info {
|
|
|
|
|
|
#endif /* ifndef _SQLITE3RTREE_H_ */
|
|
|
|
|
|
+/*
|
|
|
+** 2014 May 31
|
|
|
+**
|
|
|
+** The author disclaims copyright to this source code. In place of
|
|
|
+** a legal notice, here is a blessing:
|
|
|
+**
|
|
|
+** May you do good and not evil.
|
|
|
+** May you find forgiveness for yourself and forgive others.
|
|
|
+** May you share freely, never taking more than you give.
|
|
|
+**
|
|
|
+******************************************************************************
|
|
|
+**
|
|
|
+** Interfaces to extend FTS5. Using the interfaces defined in this file,
|
|
|
+** FTS5 may be extended with:
|
|
|
+**
|
|
|
+** * custom tokenizers, and
|
|
|
+** * custom auxiliary functions.
|
|
|
+*/
|
|
|
+
|
|
|
+
|
|
|
+#ifndef _FTS5_H
|
|
|
+#define _FTS5_H
|
|
|
+
|
|
|
+
|
|
|
+#ifdef __cplusplus
|
|
|
+extern "C" {
|
|
|
+#endif
|
|
|
+
|
|
|
+/*************************************************************************
|
|
|
+** CUSTOM AUXILIARY FUNCTIONS
|
|
|
+**
|
|
|
+** Virtual table implementations may overload SQL functions by implementing
|
|
|
+** the sqlite3_module.xFindFunction() method.
|
|
|
+*/
|
|
|
+
|
|
|
+typedef struct Fts5ExtensionApi Fts5ExtensionApi;
|
|
|
+typedef struct Fts5Context Fts5Context;
|
|
|
+typedef struct Fts5PhraseIter Fts5PhraseIter;
|
|
|
+
|
|
|
+typedef void (*fts5_extension_function)(
|
|
|
+ const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
|
|
|
+ Fts5Context *pFts, /* First arg to pass to pApi functions */
|
|
|
+ sqlite3_context *pCtx, /* Context for returning result/error */
|
|
|
+ int nVal, /* Number of values in apVal[] array */
|
|
|
+ sqlite3_value **apVal /* Array of trailing arguments */
|
|
|
+);
|
|
|
+
|
|
|
+struct Fts5PhraseIter {
|
|
|
+ const unsigned char *a;
|
|
|
+ const unsigned char *b;
|
|
|
+};
|
|
|
+
|
|
|
+/*
|
|
|
+** EXTENSION API FUNCTIONS
|
|
|
+**
|
|
|
+** xUserData(pFts):
|
|
|
+** Return a copy of the context pointer the extension function was
|
|
|
+** registered with.
|
|
|
+**
|
|
|
+** xColumnTotalSize(pFts, iCol, pnToken):
|
|
|
+** If parameter iCol is less than zero, set output variable *pnToken
|
|
|
+** to the total number of tokens in the FTS5 table. Or, if iCol is
|
|
|
+** non-negative but less than the number of columns in the table, return
|
|
|
+** the total number of tokens in column iCol, considering all rows in
|
|
|
+** the FTS5 table.
|
|
|
+**
|
|
|
+** If parameter iCol is greater than or equal to the number of columns
|
|
|
+** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
|
|
|
+** an OOM condition or IO error), an appropriate SQLite error code is
|
|
|
+** returned.
|
|
|
+**
|
|
|
+** xColumnCount(pFts):
|
|
|
+** Return the number of columns in the table.
|
|
|
+**
|
|
|
+** xColumnSize(pFts, iCol, pnToken):
|
|
|
+** If parameter iCol is less than zero, set output variable *pnToken
|
|
|
+** to the total number of tokens in the current row. Or, if iCol is
|
|
|
+** non-negative but less than the number of columns in the table, set
|
|
|
+** *pnToken to the number of tokens in column iCol of the current row.
|
|
|
+**
|
|
|
+** If parameter iCol is greater than or equal to the number of columns
|
|
|
+** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
|
|
|
+** an OOM condition or IO error), an appropriate SQLite error code is
|
|
|
+** returned.
|
|
|
+**
|
|
|
+** xColumnText:
|
|
|
+** This function attempts to retrieve the text of column iCol of the
|
|
|
+** current document. If successful, (*pz) is set to point to a buffer
|
|
|
+** containing the text in utf-8 encoding, (*pn) is set to the size in bytes
|
|
|
+** (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
|
|
|
+** if an error occurs, an SQLite error code is returned and the final values
|
|
|
+** of (*pz) and (*pn) are undefined.
|
|
|
+**
|
|
|
+** xPhraseCount:
|
|
|
+** Returns the number of phrases in the current query expression.
|
|
|
+**
|
|
|
+** xPhraseSize:
|
|
|
+** Returns the number of tokens in phrase iPhrase of the query. Phrases
|
|
|
+** are numbered starting from zero.
|
|
|
+**
|
|
|
+** xInstCount:
|
|
|
+** Set *pnInst to the total number of occurrences of all phrases within
|
|
|
+** the query within the current row. Return SQLITE_OK if successful, or
|
|
|
+** an error code (i.e. SQLITE_NOMEM) if an error occurs.
|
|
|
+**
|
|
|
+** xInst:
|
|
|
+** Query for the details of phrase match iIdx within the current row.
|
|
|
+** Phrase matches are numbered starting from zero, so the iIdx argument
|
|
|
+** should be greater than or equal to zero and smaller than the value
|
|
|
+** output by xInstCount().
|
|
|
+**
|
|
|
+** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
|
|
|
+** if an error occurs.
|
|
|
+**
|
|
|
+** xRowid:
|
|
|
+** Returns the rowid of the current row.
|
|
|
+**
|
|
|
+** xTokenize:
|
|
|
+** Tokenize text using the tokenizer belonging to the FTS5 table.
|
|
|
+**
|
|
|
+** xQueryPhrase(pFts5, iPhrase, pUserData, xCallback):
|
|
|
+** This API function is used to query the FTS table for phrase iPhrase
|
|
|
+** of the current query. Specifically, a query equivalent to:
|
|
|
+**
|
|
|
+** ... FROM ftstable WHERE ftstable MATCH $p ORDER BY rowid
|
|
|
+**
|
|
|
+** with $p set to a phrase equivalent to the phrase iPhrase of the
|
|
|
+** current query is executed. For each row visited, the callback function
|
|
|
+** passed as the fourth argument is invoked. The context and API objects
|
|
|
+** passed to the callback function may be used to access the properties of
|
|
|
+** each matched row. Invoking Api.xUserData() returns a copy of the pointer
|
|
|
+** passed as the third argument to pUserData.
|
|
|
+**
|
|
|
+** If the callback function returns any value other than SQLITE_OK, the
|
|
|
+** query is abandoned and the xQueryPhrase function returns immediately.
|
|
|
+** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK.
|
|
|
+** Otherwise, the error code is propagated upwards.
|
|
|
+**
|
|
|
+** If the query runs to completion without incident, SQLITE_OK is returned.
|
|
|
+** Or, if some error occurs before the query completes or is aborted by
|
|
|
+** the callback, an SQLite error code is returned.
|
|
|
+**
|
|
|
+**
|
|
|
+** xSetAuxdata(pFts5, pAux, xDelete)
|
|
|
+**
|
|
|
+** Save the pointer passed as the second argument as the extension functions
|
|
|
+** "auxiliary data". The pointer may then be retrieved by the current or any
|
|
|
+** future invocation of the same fts5 extension function made as part of
|
|
|
+** of the same MATCH query using the xGetAuxdata() API.
|
|
|
+**
|
|
|
+** Each extension function is allocated a single auxiliary data slot for
|
|
|
+** each FTS query (MATCH expression). If the extension function is invoked
|
|
|
+** more than once for a single FTS query, then all invocations share a
|
|
|
+** single auxiliary data context.
|
|
|
+**
|
|
|
+** If there is already an auxiliary data pointer when this function is
|
|
|
+** invoked, then it is replaced by the new pointer. If an xDelete callback
|
|
|
+** was specified along with the original pointer, it is invoked at this
|
|
|
+** point.
|
|
|
+**
|
|
|
+** The xDelete callback, if one is specified, is also invoked on the
|
|
|
+** auxiliary data pointer after the FTS5 query has finished.
|
|
|
+**
|
|
|
+** If an error (e.g. an OOM condition) occurs within this function, an
|
|
|
+** the auxiliary data is set to NULL and an error code returned. If the
|
|
|
+** xDelete parameter was not NULL, it is invoked on the auxiliary data
|
|
|
+** pointer before returning.
|
|
|
+**
|
|
|
+**
|
|
|
+** xGetAuxdata(pFts5, bClear)
|
|
|
+**
|
|
|
+** Returns the current auxiliary data pointer for the fts5 extension
|
|
|
+** function. See the xSetAuxdata() method for details.
|
|
|
+**
|
|
|
+** If the bClear argument is non-zero, then the auxiliary data is cleared
|
|
|
+** (set to NULL) before this function returns. In this case the xDelete,
|
|
|
+** if any, is not invoked.
|
|
|
+**
|
|
|
+**
|
|
|
+** xRowCount(pFts5, pnRow)
|
|
|
+**
|
|
|
+** This function is used to retrieve the total number of rows in the table.
|
|
|
+** In other words, the same value that would be returned by:
|
|
|
+**
|
|
|
+** SELECT count(*) FROM ftstable;
|
|
|
+**
|
|
|
+** xPhraseFirst()
|
|
|
+** This function is used, along with type Fts5PhraseIter and the xPhraseNext
|
|
|
+** method, to iterate through all instances of a single query phrase within
|
|
|
+** the current row. This is the same information as is accessible via the
|
|
|
+** xInstCount/xInst APIs. While the xInstCount/xInst APIs are more convenient
|
|
|
+** to use, this API may be faster under some circumstances. To iterate
|
|
|
+** through instances of phrase iPhrase, use the following code:
|
|
|
+**
|
|
|
+** Fts5PhraseIter iter;
|
|
|
+** int iCol, iOff;
|
|
|
+** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff);
|
|
|
+** iOff>=0;
|
|
|
+** pApi->xPhraseNext(pFts, &iter, &iCol, &iOff)
|
|
|
+** ){
|
|
|
+** // An instance of phrase iPhrase at offset iOff of column iCol
|
|
|
+** }
|
|
|
+**
|
|
|
+** The Fts5PhraseIter structure is defined above. Applications should not
|
|
|
+** modify this structure directly - it should only be used as shown above
|
|
|
+** with the xPhraseFirst() and xPhraseNext() API methods.
|
|
|
+**
|
|
|
+** xPhraseNext()
|
|
|
+** See xPhraseFirst above.
|
|
|
+*/
|
|
|
+struct Fts5ExtensionApi {
|
|
|
+ int iVersion; /* Currently always set to 1 */
|
|
|
+
|
|
|
+ void *(*xUserData)(Fts5Context*);
|
|
|
+
|
|
|
+ int (*xColumnCount)(Fts5Context*);
|
|
|
+ int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
|
|
|
+ int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken);
|
|
|
+
|
|
|
+ int (*xTokenize)(Fts5Context*,
|
|
|
+ const char *pText, int nText, /* Text to tokenize */
|
|
|
+ void *pCtx, /* Context passed to xToken() */
|
|
|
+ int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
|
|
|
+ );
|
|
|
+
|
|
|
+ int (*xPhraseCount)(Fts5Context*);
|
|
|
+ int (*xPhraseSize)(Fts5Context*, int iPhrase);
|
|
|
+
|
|
|
+ int (*xInstCount)(Fts5Context*, int *pnInst);
|
|
|
+ int (*xInst)(Fts5Context*, int iIdx, int *piPhrase, int *piCol, int *piOff);
|
|
|
+
|
|
|
+ sqlite3_int64 (*xRowid)(Fts5Context*);
|
|
|
+ int (*xColumnText)(Fts5Context*, int iCol, const char **pz, int *pn);
|
|
|
+ int (*xColumnSize)(Fts5Context*, int iCol, int *pnToken);
|
|
|
+
|
|
|
+ int (*xQueryPhrase)(Fts5Context*, int iPhrase, void *pUserData,
|
|
|
+ int(*)(const Fts5ExtensionApi*,Fts5Context*,void*)
|
|
|
+ );
|
|
|
+ int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*));
|
|
|
+ void *(*xGetAuxdata)(Fts5Context*, int bClear);
|
|
|
+
|
|
|
+ void (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
|
|
|
+ void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
|
|
|
+};
|
|
|
+
|
|
|
+/*
|
|
|
+** CUSTOM AUXILIARY FUNCTIONS
|
|
|
+*************************************************************************/
|
|
|
+
|
|
|
+/*************************************************************************
|
|
|
+** CUSTOM TOKENIZERS
|
|
|
+**
|
|
|
+** Applications may also register custom tokenizer types. A tokenizer
|
|
|
+** is registered by providing fts5 with a populated instance of the
|
|
|
+** following structure. All structure methods must be defined, setting
|
|
|
+** any member of the fts5_tokenizer struct to NULL leads to undefined
|
|
|
+** behaviour. The structure methods are expected to function as follows:
|
|
|
+**
|
|
|
+** xCreate:
|
|
|
+** This function is used to allocate and inititalize a tokenizer instance.
|
|
|
+** A tokenizer instance is required to actually tokenize text.
|
|
|
+**
|
|
|
+** The first argument passed to this function is a copy of the (void*)
|
|
|
+** pointer provided by the application when the fts5_tokenizer object
|
|
|
+** was registered with FTS5 (the third argument to xCreateTokenizer()).
|
|
|
+** The second and third arguments are an array of nul-terminated strings
|
|
|
+** containing the tokenizer arguments, if any, specified following the
|
|
|
+** tokenizer name as part of the CREATE VIRTUAL TABLE statement used
|
|
|
+** to create the FTS5 table.
|
|
|
+**
|
|
|
+** The final argument is an output variable. If successful, (*ppOut)
|
|
|
+** should be set to point to the new tokenizer handle and SQLITE_OK
|
|
|
+** returned. If an error occurs, some value other than SQLITE_OK should
|
|
|
+** be returned. In this case, fts5 assumes that the final value of *ppOut
|
|
|
+** is undefined.
|
|
|
+**
|
|
|
+** xDelete:
|
|
|
+** This function is invoked to delete a tokenizer handle previously
|
|
|
+** allocated using xCreate(). Fts5 guarantees that this function will
|
|
|
+** be invoked exactly once for each successful call to xCreate().
|
|
|
+**
|
|
|
+** xTokenize:
|
|
|
+** This function is expected to tokenize the nText byte string indicated
|
|
|
+** by argument pText. pText may or may not be nul-terminated. The first
|
|
|
+** argument passed to this function is a pointer to an Fts5Tokenizer object
|
|
|
+** returned by an earlier call to xCreate().
|
|
|
+**
|
|
|
+** The second argument indicates the reason that FTS5 is requesting
|
|
|
+** tokenization of the supplied text. This is always one of the following
|
|
|
+** four values:
|
|
|
+**
|
|
|
+** <ul><li> <b>FTS5_TOKENIZE_DOCUMENT</b> - A document is being inserted into
|
|
|
+** or removed from the FTS table. The tokenizer is being invoked to
|
|
|
+** determine the set of tokens to add to (or delete from) the
|
|
|
+** FTS index.
|
|
|
+**
|
|
|
+** <li> <b>FTS5_TOKENIZE_QUERY</b> - A MATCH query is being executed
|
|
|
+** against the FTS index. The tokenizer is being called to tokenize
|
|
|
+** a bareword or quoted string specified as part of the query.
|
|
|
+**
|
|
|
+** <li> <b>(FTS5_TOKENIZE_QUERY | FTS5_TOKENIZE_PREFIX)</b> - Same as
|
|
|
+** FTS5_TOKENIZE_QUERY, except that the bareword or quoted string is
|
|
|
+** followed by a "*" character, indicating that the last token
|
|
|
+** returned by the tokenizer will be treated as a token prefix.
|
|
|
+**
|
|
|
+** <li> <b>FTS5_TOKENIZE_AUX</b> - The tokenizer is being invoked to
|
|
|
+** satisfy an fts5_api.xTokenize() request made by an auxiliary
|
|
|
+** function. Or an fts5_api.xColumnSize() request made by the same
|
|
|
+** on a columnsize=0 database.
|
|
|
+** </ul>
|
|
|
+**
|
|
|
+** For each token in the input string, the supplied callback xToken() must
|
|
|
+** be invoked. The first argument to it should be a copy of the pointer
|
|
|
+** passed as the second argument to xTokenize(). The third and fourth
|
|
|
+** arguments are a pointer to a buffer containing the token text, and the
|
|
|
+** size of the token in bytes. The 4th and 5th arguments are the byte offsets
|
|
|
+** of the first byte of and first byte immediately following the text from
|
|
|
+** which the token is derived within the input.
|
|
|
+**
|
|
|
+** The second argument passed to the xToken() callback ("tflags") should
|
|
|
+** normally be set to 0. The exception is if the tokenizer supports
|
|
|
+** synonyms. In this case see the discussion below for details.
|
|
|
+**
|
|
|
+** FTS5 assumes the xToken() callback is invoked for each token in the
|
|
|
+** order that they occur within the input text.
|
|
|
+**
|
|
|
+** If an xToken() callback returns any value other than SQLITE_OK, then
|
|
|
+** the tokenization should be abandoned and the xTokenize() method should
|
|
|
+** immediately return a copy of the xToken() return value. Or, if the
|
|
|
+** input buffer is exhausted, xTokenize() should return SQLITE_OK. Finally,
|
|
|
+** if an error occurs with the xTokenize() implementation itself, it
|
|
|
+** may abandon the tokenization and return any error code other than
|
|
|
+** SQLITE_OK or SQLITE_DONE.
|
|
|
+**
|
|
|
+** SYNONYM SUPPORT
|
|
|
+**
|
|
|
+** Custom tokenizers may also support synonyms. Consider a case in which a
|
|
|
+** user wishes to query for a phrase such as "first place". Using the
|
|
|
+** built-in tokenizers, the FTS5 query 'first + place' will match instances
|
|
|
+** of "first place" within the document set, but not alternative forms
|
|
|
+** such as "1st place". In some applications, it would be better to match
|
|
|
+** all instances of "first place" or "1st place" regardless of which form
|
|
|
+** the user specified in the MATCH query text.
|
|
|
+**
|
|
|
+** There are several ways to approach this in FTS5:
|
|
|
+**
|
|
|
+** <ol><li> By mapping all synonyms to a single token. In this case, the
|
|
|
+** In the above example, this means that the tokenizer returns the
|
|
|
+** same token for inputs "first" and "1st". Say that token is in
|
|
|
+** fact "first", so that when the user inserts the document "I won
|
|
|
+** 1st place" entries are added to the index for tokens "i", "won",
|
|
|
+** "first" and "place". If the user then queries for '1st + place',
|
|
|
+** the tokenizer substitutes "first" for "1st" and the query works
|
|
|
+** as expected.
|
|
|
+**
|
|
|
+** <li> By adding multiple synonyms for a single term to the FTS index.
|
|
|
+** In this case, when tokenizing query text, the tokenizer may
|
|
|
+** provide multiple synonyms for a single term within the document.
|
|
|
+** FTS5 then queries the index for each synonym individually. For
|
|
|
+** example, faced with the query:
|
|
|
+**
|
|
|
+** <codeblock>
|
|
|
+** ... MATCH 'first place'</codeblock>
|
|
|
+**
|
|
|
+** the tokenizer offers both "1st" and "first" as synonyms for the
|
|
|
+** first token in the MATCH query and FTS5 effectively runs a query
|
|
|
+** similar to:
|
|
|
+**
|
|
|
+** <codeblock>
|
|
|
+** ... MATCH '(first OR 1st) place'</codeblock>
|
|
|
+**
|
|
|
+** except that, for the purposes of auxiliary functions, the query
|
|
|
+** still appears to contain just two phrases - "(first OR 1st)"
|
|
|
+** being treated as a single phrase.
|
|
|
+**
|
|
|
+** <li> By adding multiple synonyms for a single term to the FTS index.
|
|
|
+** Using this method, when tokenizing document text, the tokenizer
|
|
|
+** provides multiple synonyms for each token. So that when a
|
|
|
+** document such as "I won first place" is tokenized, entries are
|
|
|
+** added to the FTS index for "i", "won", "first", "1st" and
|
|
|
+** "place".
|
|
|
+**
|
|
|
+** This way, even if the tokenizer does not provide synonyms
|
|
|
+** when tokenizing query text (it should not - to do would be
|
|
|
+** inefficient), it doesn't matter if the user queries for
|
|
|
+** 'first + place' or '1st + place', as there are entires in the
|
|
|
+** FTS index corresponding to both forms of the first token.
|
|
|
+** </ol>
|
|
|
+**
|
|
|
+** Whether it is parsing document or query text, any call to xToken that
|
|
|
+** specifies a <i>tflags</i> argument with the FTS5_TOKEN_COLOCATED bit
|
|
|
+** is considered to supply a synonym for the previous token. For example,
|
|
|
+** when parsing the document "I won first place", a tokenizer that supports
|
|
|
+** synonyms would call xToken() 5 times, as follows:
|
|
|
+**
|
|
|
+** <codeblock>
|
|
|
+** xToken(pCtx, 0, "i", 1, 0, 1);
|
|
|
+** xToken(pCtx, 0, "won", 3, 2, 5);
|
|
|
+** xToken(pCtx, 0, "first", 5, 6, 11);
|
|
|
+** xToken(pCtx, FTS5_TOKEN_COLOCATED, "1st", 3, 6, 11);
|
|
|
+** xToken(pCtx, 0, "place", 5, 12, 17);
|
|
|
+**</codeblock>
|
|
|
+**
|
|
|
+** It is an error to specify the FTS5_TOKEN_COLOCATED flag the first time
|
|
|
+** xToken() is called. Multiple synonyms may be specified for a single token
|
|
|
+** by making multiple calls to xToken(FTS5_TOKEN_COLOCATED) in sequence.
|
|
|
+** There is no limit to the number of synonyms that may be provided for a
|
|
|
+** single token.
|
|
|
+**
|
|
|
+** In many cases, method (1) above is the best approach. It does not add
|
|
|
+** extra data to the FTS index or require FTS5 to query for multiple terms,
|
|
|
+** so it is efficient in terms of disk space and query speed. However, it
|
|
|
+** does not support prefix queries very well. If, as suggested above, the
|
|
|
+** token "first" is subsituted for "1st" by the tokenizer, then the query:
|
|
|
+**
|
|
|
+** <codeblock>
|
|
|
+** ... MATCH '1s*'</codeblock>
|
|
|
+**
|
|
|
+** will not match documents that contain the token "1st" (as the tokenizer
|
|
|
+** will probably not map "1s" to any prefix of "first").
|
|
|
+**
|
|
|
+** For full prefix support, method (3) may be preferred. In this case,
|
|
|
+** because the index contains entries for both "first" and "1st", prefix
|
|
|
+** queries such as 'fi*' or '1s*' will match correctly. However, because
|
|
|
+** extra entries are added to the FTS index, this method uses more space
|
|
|
+** within the database.
|
|
|
+**
|
|
|
+** Method (2) offers a midpoint between (1) and (3). Using this method,
|
|
|
+** a query such as '1s*' will match documents that contain the literal
|
|
|
+** token "1st", but not "first" (assuming the tokenizer is not able to
|
|
|
+** provide synonyms for prefixes). However, a non-prefix query like '1st'
|
|
|
+** will match against "1st" and "first". This method does not require
|
|
|
+** extra disk space, as no extra entries are added to the FTS index.
|
|
|
+** On the other hand, it may require more CPU cycles to run MATCH queries,
|
|
|
+** as separate queries of the FTS index are required for each synonym.
|
|
|
+**
|
|
|
+** When using methods (2) or (3), it is important that the tokenizer only
|
|
|
+** provide synonyms when tokenizing document text (method (2)) or query
|
|
|
+** text (method (3)), not both. Doing so will not cause any errors, but is
|
|
|
+** inefficient.
|
|
|
+*/
|
|
|
+typedef struct Fts5Tokenizer Fts5Tokenizer;
|
|
|
+typedef struct fts5_tokenizer fts5_tokenizer;
|
|
|
+struct fts5_tokenizer {
|
|
|
+ int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
|
|
|
+ void (*xDelete)(Fts5Tokenizer*);
|
|
|
+ int (*xTokenize)(Fts5Tokenizer*,
|
|
|
+ void *pCtx,
|
|
|
+ int flags, /* Mask of FTS5_TOKENIZE_* flags */
|
|
|
+ const char *pText, int nText,
|
|
|
+ int (*xToken)(
|
|
|
+ void *pCtx, /* Copy of 2nd argument to xTokenize() */
|
|
|
+ int tflags, /* Mask of FTS5_TOKEN_* flags */
|
|
|
+ const char *pToken, /* Pointer to buffer containing token */
|
|
|
+ int nToken, /* Size of token in bytes */
|
|
|
+ int iStart, /* Byte offset of token within input text */
|
|
|
+ int iEnd /* Byte offset of end of token within input text */
|
|
|
+ )
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+/* Flags that may be passed as the third argument to xTokenize() */
|
|
|
+#define FTS5_TOKENIZE_QUERY 0x0001
|
|
|
+#define FTS5_TOKENIZE_PREFIX 0x0002
|
|
|
+#define FTS5_TOKENIZE_DOCUMENT 0x0004
|
|
|
+#define FTS5_TOKENIZE_AUX 0x0008
|
|
|
+
|
|
|
+/* Flags that may be passed by the tokenizer implementation back to FTS5
|
|
|
+** as the third argument to the supplied xToken callback. */
|
|
|
+#define FTS5_TOKEN_COLOCATED 0x0001 /* Same position as prev. token */
|
|
|
+
|
|
|
+/*
|
|
|
+** END OF CUSTOM TOKENIZERS
|
|
|
+*************************************************************************/
|
|
|
+
|
|
|
+/*************************************************************************
|
|
|
+** FTS5 EXTENSION REGISTRATION API
|
|
|
+*/
|
|
|
+typedef struct fts5_api fts5_api;
|
|
|
+struct fts5_api {
|
|
|
+ int iVersion; /* Currently always set to 2 */
|
|
|
+
|
|
|
+ /* Create a new tokenizer */
|
|
|
+ int (*xCreateTokenizer)(
|
|
|
+ fts5_api *pApi,
|
|
|
+ const char *zName,
|
|
|
+ void *pContext,
|
|
|
+ fts5_tokenizer *pTokenizer,
|
|
|
+ void (*xDestroy)(void*)
|
|
|
+ );
|
|
|
+
|
|
|
+ /* Find an existing tokenizer */
|
|
|
+ int (*xFindTokenizer)(
|
|
|
+ fts5_api *pApi,
|
|
|
+ const char *zName,
|
|
|
+ void **ppContext,
|
|
|
+ fts5_tokenizer *pTokenizer
|
|
|
+ );
|
|
|
+
|
|
|
+ /* Create a new auxiliary function */
|
|
|
+ int (*xCreateFunction)(
|
|
|
+ fts5_api *pApi,
|
|
|
+ const char *zName,
|
|
|
+ void *pContext,
|
|
|
+ fts5_extension_function xFunction,
|
|
|
+ void (*xDestroy)(void*)
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+/*
|
|
|
+** END OF REGISTRATION API
|
|
|
+*************************************************************************/
|
|
|
+
|
|
|
+#ifdef __cplusplus
|
|
|
+} /* end of the 'extern "C"' block */
|
|
|
+#endif
|
|
|
+
|
|
|
+#endif /* _FTS5_H */
|
|
|
+
|
|
|
+
|