Snapshot of upstream SQLite 3.40.1
[sqlcipher.git] / ext / fts5 / fts5_main.c
blobccdcf7b57f66697547a54508c421acba49721e00
1 /*
2 ** 2014 Jun 09
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.
11 ******************************************************************************
13 ** This is an SQLite module implementing full-text search.
17 #include "fts5Int.h"
20 ** This variable is set to false when running tests for which the on disk
21 ** structures should not be corrupt. Otherwise, true. If it is false, extra
22 ** assert() conditions in the fts5 code are activated - conditions that are
23 ** only true if it is guaranteed that the fts5 database is not corrupt.
25 #ifdef SQLITE_DEBUG
26 int sqlite3_fts5_may_be_corrupt = 1;
27 #endif
30 typedef struct Fts5Auxdata Fts5Auxdata;
31 typedef struct Fts5Auxiliary Fts5Auxiliary;
32 typedef struct Fts5Cursor Fts5Cursor;
33 typedef struct Fts5FullTable Fts5FullTable;
34 typedef struct Fts5Sorter Fts5Sorter;
35 typedef struct Fts5TokenizerModule Fts5TokenizerModule;
38 ** NOTES ON TRANSACTIONS:
40 ** SQLite invokes the following virtual table methods as transactions are
41 ** opened and closed by the user:
43 ** xBegin(): Start of a new transaction.
44 ** xSync(): Initial part of two-phase commit.
45 ** xCommit(): Final part of two-phase commit.
46 ** xRollback(): Rollback the transaction.
48 ** Anything that is required as part of a commit that may fail is performed
49 ** in the xSync() callback. Current versions of SQLite ignore any errors
50 ** returned by xCommit().
52 ** And as sub-transactions are opened/closed:
54 ** xSavepoint(int S): Open savepoint S.
55 ** xRelease(int S): Commit and close savepoint S.
56 ** xRollbackTo(int S): Rollback to start of savepoint S.
58 ** During a write-transaction the fts5_index.c module may cache some data
59 ** in-memory. It is flushed to disk whenever xSync(), xRelease() or
60 ** xSavepoint() is called. And discarded whenever xRollback() or xRollbackTo()
61 ** is called.
63 ** Additionally, if SQLITE_DEBUG is defined, an instance of the following
64 ** structure is used to record the current transaction state. This information
65 ** is not required, but it is used in the assert() statements executed by
66 ** function fts5CheckTransactionState() (see below).
68 struct Fts5TransactionState {
69 int eState; /* 0==closed, 1==open, 2==synced */
70 int iSavepoint; /* Number of open savepoints (0 -> none) */
74 ** A single object of this type is allocated when the FTS5 module is
75 ** registered with a database handle. It is used to store pointers to
76 ** all registered FTS5 extensions - tokenizers and auxiliary functions.
78 struct Fts5Global {
79 fts5_api api; /* User visible part of object (see fts5.h) */
80 sqlite3 *db; /* Associated database connection */
81 i64 iNextId; /* Used to allocate unique cursor ids */
82 Fts5Auxiliary *pAux; /* First in list of all aux. functions */
83 Fts5TokenizerModule *pTok; /* First in list of all tokenizer modules */
84 Fts5TokenizerModule *pDfltTok; /* Default tokenizer module */
85 Fts5Cursor *pCsr; /* First in list of all open cursors */
89 ** Each auxiliary function registered with the FTS5 module is represented
90 ** by an object of the following type. All such objects are stored as part
91 ** of the Fts5Global.pAux list.
93 struct Fts5Auxiliary {
94 Fts5Global *pGlobal; /* Global context for this function */
95 char *zFunc; /* Function name (nul-terminated) */
96 void *pUserData; /* User-data pointer */
97 fts5_extension_function xFunc; /* Callback function */
98 void (*xDestroy)(void*); /* Destructor function */
99 Fts5Auxiliary *pNext; /* Next registered auxiliary function */
103 ** Each tokenizer module registered with the FTS5 module is represented
104 ** by an object of the following type. All such objects are stored as part
105 ** of the Fts5Global.pTok list.
107 struct Fts5TokenizerModule {
108 char *zName; /* Name of tokenizer */
109 void *pUserData; /* User pointer passed to xCreate() */
110 fts5_tokenizer x; /* Tokenizer functions */
111 void (*xDestroy)(void*); /* Destructor function */
112 Fts5TokenizerModule *pNext; /* Next registered tokenizer module */
115 struct Fts5FullTable {
116 Fts5Table p; /* Public class members from fts5Int.h */
117 Fts5Storage *pStorage; /* Document store */
118 Fts5Global *pGlobal; /* Global (connection wide) data */
119 Fts5Cursor *pSortCsr; /* Sort data from this cursor */
120 #ifdef SQLITE_DEBUG
121 struct Fts5TransactionState ts;
122 #endif
125 struct Fts5MatchPhrase {
126 Fts5Buffer *pPoslist; /* Pointer to current poslist */
127 int nTerm; /* Size of phrase in terms */
131 ** pStmt:
132 ** SELECT rowid, <fts> FROM <fts> ORDER BY +rank;
134 ** aIdx[]:
135 ** There is one entry in the aIdx[] array for each phrase in the query,
136 ** the value of which is the offset within aPoslist[] following the last
137 ** byte of the position list for the corresponding phrase.
139 struct Fts5Sorter {
140 sqlite3_stmt *pStmt;
141 i64 iRowid; /* Current rowid */
142 const u8 *aPoslist; /* Position lists for current row */
143 int nIdx; /* Number of entries in aIdx[] */
144 int aIdx[1]; /* Offsets into aPoslist for current row */
149 ** Virtual-table cursor object.
151 ** iSpecial:
152 ** If this is a 'special' query (refer to function fts5SpecialMatch()),
153 ** then this variable contains the result of the query.
155 ** iFirstRowid, iLastRowid:
156 ** These variables are only used for FTS5_PLAN_MATCH cursors. Assuming the
157 ** cursor iterates in ascending order of rowids, iFirstRowid is the lower
158 ** limit of rowids to return, and iLastRowid the upper. In other words, the
159 ** WHERE clause in the user's query might have been:
161 ** <tbl> MATCH <expr> AND rowid BETWEEN $iFirstRowid AND $iLastRowid
163 ** If the cursor iterates in descending order of rowid, iFirstRowid
164 ** is the upper limit (i.e. the "first" rowid visited) and iLastRowid
165 ** the lower.
167 struct Fts5Cursor {
168 sqlite3_vtab_cursor base; /* Base class used by SQLite core */
169 Fts5Cursor *pNext; /* Next cursor in Fts5Cursor.pCsr list */
170 int *aColumnSize; /* Values for xColumnSize() */
171 i64 iCsrId; /* Cursor id */
173 /* Zero from this point onwards on cursor reset */
174 int ePlan; /* FTS5_PLAN_XXX value */
175 int bDesc; /* True for "ORDER BY rowid DESC" queries */
176 i64 iFirstRowid; /* Return no rowids earlier than this */
177 i64 iLastRowid; /* Return no rowids later than this */
178 sqlite3_stmt *pStmt; /* Statement used to read %_content */
179 Fts5Expr *pExpr; /* Expression for MATCH queries */
180 Fts5Sorter *pSorter; /* Sorter for "ORDER BY rank" queries */
181 int csrflags; /* Mask of cursor flags (see below) */
182 i64 iSpecial; /* Result of special query */
184 /* "rank" function. Populated on demand from vtab.xColumn(). */
185 char *zRank; /* Custom rank function */
186 char *zRankArgs; /* Custom rank function args */
187 Fts5Auxiliary *pRank; /* Rank callback (or NULL) */
188 int nRankArg; /* Number of trailing arguments for rank() */
189 sqlite3_value **apRankArg; /* Array of trailing arguments */
190 sqlite3_stmt *pRankArgStmt; /* Origin of objects in apRankArg[] */
192 /* Auxiliary data storage */
193 Fts5Auxiliary *pAux; /* Currently executing extension function */
194 Fts5Auxdata *pAuxdata; /* First in linked list of saved aux-data */
196 /* Cache used by auxiliary functions xInst() and xInstCount() */
197 Fts5PoslistReader *aInstIter; /* One for each phrase */
198 int nInstAlloc; /* Size of aInst[] array (entries / 3) */
199 int nInstCount; /* Number of phrase instances */
200 int *aInst; /* 3 integers per phrase instance */
204 ** Bits that make up the "idxNum" parameter passed indirectly by
205 ** xBestIndex() to xFilter().
207 #define FTS5_BI_MATCH 0x0001 /* <tbl> MATCH ? */
208 #define FTS5_BI_RANK 0x0002 /* rank MATCH ? */
209 #define FTS5_BI_ROWID_EQ 0x0004 /* rowid == ? */
210 #define FTS5_BI_ROWID_LE 0x0008 /* rowid <= ? */
211 #define FTS5_BI_ROWID_GE 0x0010 /* rowid >= ? */
213 #define FTS5_BI_ORDER_RANK 0x0020
214 #define FTS5_BI_ORDER_ROWID 0x0040
215 #define FTS5_BI_ORDER_DESC 0x0080
218 ** Values for Fts5Cursor.csrflags
220 #define FTS5CSR_EOF 0x01
221 #define FTS5CSR_REQUIRE_CONTENT 0x02
222 #define FTS5CSR_REQUIRE_DOCSIZE 0x04
223 #define FTS5CSR_REQUIRE_INST 0x08
224 #define FTS5CSR_FREE_ZRANK 0x10
225 #define FTS5CSR_REQUIRE_RESEEK 0x20
226 #define FTS5CSR_REQUIRE_POSLIST 0x40
228 #define BitFlagAllTest(x,y) (((x) & (y))==(y))
229 #define BitFlagTest(x,y) (((x) & (y))!=0)
233 ** Macros to Set(), Clear() and Test() cursor flags.
235 #define CsrFlagSet(pCsr, flag) ((pCsr)->csrflags |= (flag))
236 #define CsrFlagClear(pCsr, flag) ((pCsr)->csrflags &= ~(flag))
237 #define CsrFlagTest(pCsr, flag) ((pCsr)->csrflags & (flag))
239 struct Fts5Auxdata {
240 Fts5Auxiliary *pAux; /* Extension to which this belongs */
241 void *pPtr; /* Pointer value */
242 void(*xDelete)(void*); /* Destructor */
243 Fts5Auxdata *pNext; /* Next object in linked list */
246 #ifdef SQLITE_DEBUG
247 #define FTS5_BEGIN 1
248 #define FTS5_SYNC 2
249 #define FTS5_COMMIT 3
250 #define FTS5_ROLLBACK 4
251 #define FTS5_SAVEPOINT 5
252 #define FTS5_RELEASE 6
253 #define FTS5_ROLLBACKTO 7
254 static void fts5CheckTransactionState(Fts5FullTable *p, int op, int iSavepoint){
255 switch( op ){
256 case FTS5_BEGIN:
257 assert( p->ts.eState==0 );
258 p->ts.eState = 1;
259 p->ts.iSavepoint = -1;
260 break;
262 case FTS5_SYNC:
263 assert( p->ts.eState==1 || p->ts.eState==2 );
264 p->ts.eState = 2;
265 break;
267 case FTS5_COMMIT:
268 assert( p->ts.eState==2 );
269 p->ts.eState = 0;
270 break;
272 case FTS5_ROLLBACK:
273 assert( p->ts.eState==1 || p->ts.eState==2 || p->ts.eState==0 );
274 p->ts.eState = 0;
275 break;
277 case FTS5_SAVEPOINT:
278 assert( p->ts.eState>=1 );
279 assert( iSavepoint>=0 );
280 assert( iSavepoint>=p->ts.iSavepoint );
281 p->ts.iSavepoint = iSavepoint;
282 break;
284 case FTS5_RELEASE:
285 assert( p->ts.eState>=1 );
286 assert( iSavepoint>=0 );
287 assert( iSavepoint<=p->ts.iSavepoint );
288 p->ts.iSavepoint = iSavepoint-1;
289 break;
291 case FTS5_ROLLBACKTO:
292 assert( p->ts.eState>=1 );
293 assert( iSavepoint>=-1 );
294 /* The following assert() can fail if another vtab strikes an error
295 ** within an xSavepoint() call then SQLite calls xRollbackTo() - without
296 ** having called xSavepoint() on this vtab. */
297 /* assert( iSavepoint<=p->ts.iSavepoint ); */
298 p->ts.iSavepoint = iSavepoint;
299 break;
302 #else
303 # define fts5CheckTransactionState(x,y,z)
304 #endif
307 ** Return true if pTab is a contentless table.
309 static int fts5IsContentless(Fts5FullTable *pTab){
310 return pTab->p.pConfig->eContent==FTS5_CONTENT_NONE;
314 ** Delete a virtual table handle allocated by fts5InitVtab().
316 static void fts5FreeVtab(Fts5FullTable *pTab){
317 if( pTab ){
318 sqlite3Fts5IndexClose(pTab->p.pIndex);
319 sqlite3Fts5StorageClose(pTab->pStorage);
320 sqlite3Fts5ConfigFree(pTab->p.pConfig);
321 sqlite3_free(pTab);
326 ** The xDisconnect() virtual table method.
328 static int fts5DisconnectMethod(sqlite3_vtab *pVtab){
329 fts5FreeVtab((Fts5FullTable*)pVtab);
330 return SQLITE_OK;
334 ** The xDestroy() virtual table method.
336 static int fts5DestroyMethod(sqlite3_vtab *pVtab){
337 Fts5Table *pTab = (Fts5Table*)pVtab;
338 int rc = sqlite3Fts5DropAll(pTab->pConfig);
339 if( rc==SQLITE_OK ){
340 fts5FreeVtab((Fts5FullTable*)pVtab);
342 return rc;
346 ** This function is the implementation of both the xConnect and xCreate
347 ** methods of the FTS3 virtual table.
349 ** The argv[] array contains the following:
351 ** argv[0] -> module name ("fts5")
352 ** argv[1] -> database name
353 ** argv[2] -> table name
354 ** argv[...] -> "column name" and other module argument fields.
356 static int fts5InitVtab(
357 int bCreate, /* True for xCreate, false for xConnect */
358 sqlite3 *db, /* The SQLite database connection */
359 void *pAux, /* Hash table containing tokenizers */
360 int argc, /* Number of elements in argv array */
361 const char * const *argv, /* xCreate/xConnect argument array */
362 sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */
363 char **pzErr /* Write any error message here */
365 Fts5Global *pGlobal = (Fts5Global*)pAux;
366 const char **azConfig = (const char**)argv;
367 int rc = SQLITE_OK; /* Return code */
368 Fts5Config *pConfig = 0; /* Results of parsing argc/argv */
369 Fts5FullTable *pTab = 0; /* New virtual table object */
371 /* Allocate the new vtab object and parse the configuration */
372 pTab = (Fts5FullTable*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5FullTable));
373 if( rc==SQLITE_OK ){
374 rc = sqlite3Fts5ConfigParse(pGlobal, db, argc, azConfig, &pConfig, pzErr);
375 assert( (rc==SQLITE_OK && *pzErr==0) || pConfig==0 );
377 if( rc==SQLITE_OK ){
378 pTab->p.pConfig = pConfig;
379 pTab->pGlobal = pGlobal;
382 /* Open the index sub-system */
383 if( rc==SQLITE_OK ){
384 rc = sqlite3Fts5IndexOpen(pConfig, bCreate, &pTab->p.pIndex, pzErr);
387 /* Open the storage sub-system */
388 if( rc==SQLITE_OK ){
389 rc = sqlite3Fts5StorageOpen(
390 pConfig, pTab->p.pIndex, bCreate, &pTab->pStorage, pzErr
394 /* Call sqlite3_declare_vtab() */
395 if( rc==SQLITE_OK ){
396 rc = sqlite3Fts5ConfigDeclareVtab(pConfig);
399 /* Load the initial configuration */
400 if( rc==SQLITE_OK ){
401 assert( pConfig->pzErrmsg==0 );
402 pConfig->pzErrmsg = pzErr;
403 rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
404 sqlite3Fts5IndexRollback(pTab->p.pIndex);
405 pConfig->pzErrmsg = 0;
408 if( rc!=SQLITE_OK ){
409 fts5FreeVtab(pTab);
410 pTab = 0;
411 }else if( bCreate ){
412 fts5CheckTransactionState(pTab, FTS5_BEGIN, 0);
414 *ppVTab = (sqlite3_vtab*)pTab;
415 return rc;
419 ** The xConnect() and xCreate() methods for the virtual table. All the
420 ** work is done in function fts5InitVtab().
422 static int fts5ConnectMethod(
423 sqlite3 *db, /* Database connection */
424 void *pAux, /* Pointer to tokenizer hash table */
425 int argc, /* Number of elements in argv array */
426 const char * const *argv, /* xCreate/xConnect argument array */
427 sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */
428 char **pzErr /* OUT: sqlite3_malloc'd error message */
430 return fts5InitVtab(0, db, pAux, argc, argv, ppVtab, pzErr);
432 static int fts5CreateMethod(
433 sqlite3 *db, /* Database connection */
434 void *pAux, /* Pointer to tokenizer hash table */
435 int argc, /* Number of elements in argv array */
436 const char * const *argv, /* xCreate/xConnect argument array */
437 sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */
438 char **pzErr /* OUT: sqlite3_malloc'd error message */
440 return fts5InitVtab(1, db, pAux, argc, argv, ppVtab, pzErr);
444 ** The different query plans.
446 #define FTS5_PLAN_MATCH 1 /* (<tbl> MATCH ?) */
447 #define FTS5_PLAN_SOURCE 2 /* A source cursor for SORTED_MATCH */
448 #define FTS5_PLAN_SPECIAL 3 /* An internal query */
449 #define FTS5_PLAN_SORTED_MATCH 4 /* (<tbl> MATCH ? ORDER BY rank) */
450 #define FTS5_PLAN_SCAN 5 /* No usable constraint */
451 #define FTS5_PLAN_ROWID 6 /* (rowid = ?) */
454 ** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this
455 ** extension is currently being used by a version of SQLite too old to
456 ** support index-info flags. In that case this function is a no-op.
458 static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){
459 #if SQLITE_VERSION_NUMBER>=3008012
460 #ifndef SQLITE_CORE
461 if( sqlite3_libversion_number()>=3008012 )
462 #endif
464 pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE;
466 #endif
469 static int fts5UsePatternMatch(
470 Fts5Config *pConfig,
471 struct sqlite3_index_constraint *p
473 assert( FTS5_PATTERN_GLOB==SQLITE_INDEX_CONSTRAINT_GLOB );
474 assert( FTS5_PATTERN_LIKE==SQLITE_INDEX_CONSTRAINT_LIKE );
475 if( pConfig->ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
476 return 1;
478 if( pConfig->ePattern==FTS5_PATTERN_LIKE
479 && (p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB)
481 return 1;
483 return 0;
487 ** Implementation of the xBestIndex method for FTS5 tables. Within the
488 ** WHERE constraint, it searches for the following:
490 ** 1. A MATCH constraint against the table column.
491 ** 2. A MATCH constraint against the "rank" column.
492 ** 3. A MATCH constraint against some other column.
493 ** 4. An == constraint against the rowid column.
494 ** 5. A < or <= constraint against the rowid column.
495 ** 6. A > or >= constraint against the rowid column.
497 ** Within the ORDER BY, the following are supported:
499 ** 5. ORDER BY rank [ASC|DESC]
500 ** 6. ORDER BY rowid [ASC|DESC]
502 ** Information for the xFilter call is passed via both the idxNum and
503 ** idxStr variables. Specifically, idxNum is a bitmask of the following
504 ** flags used to encode the ORDER BY clause:
506 ** FTS5_BI_ORDER_RANK
507 ** FTS5_BI_ORDER_ROWID
508 ** FTS5_BI_ORDER_DESC
510 ** idxStr is used to encode data from the WHERE clause. For each argument
511 ** passed to the xFilter method, the following is appended to idxStr:
513 ** Match against table column: "m"
514 ** Match against rank column: "r"
515 ** Match against other column: "M<column-number>"
516 ** LIKE against other column: "L<column-number>"
517 ** GLOB against other column: "G<column-number>"
518 ** Equality constraint against the rowid: "="
519 ** A < or <= against the rowid: "<"
520 ** A > or >= against the rowid: ">"
522 ** This function ensures that there is at most one "r" or "=". And that if
523 ** there exists an "=" then there is no "<" or ">".
525 ** Costs are assigned as follows:
527 ** a) If an unusable MATCH operator is present in the WHERE clause, the
528 ** cost is unconditionally set to 1e50 (a really big number).
530 ** a) If a MATCH operator is present, the cost depends on the other
531 ** constraints also present. As follows:
533 ** * No other constraints: cost=1000.0
534 ** * One rowid range constraint: cost=750.0
535 ** * Both rowid range constraints: cost=500.0
536 ** * An == rowid constraint: cost=100.0
538 ** b) Otherwise, if there is no MATCH:
540 ** * No other constraints: cost=1000000.0
541 ** * One rowid range constraint: cost=750000.0
542 ** * Both rowid range constraints: cost=250000.0
543 ** * An == rowid constraint: cost=10.0
545 ** Costs are not modified by the ORDER BY clause.
547 static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
548 Fts5Table *pTab = (Fts5Table*)pVTab;
549 Fts5Config *pConfig = pTab->pConfig;
550 const int nCol = pConfig->nCol;
551 int idxFlags = 0; /* Parameter passed through to xFilter() */
552 int i;
554 char *idxStr;
555 int iIdxStr = 0;
556 int iCons = 0;
558 int bSeenEq = 0;
559 int bSeenGt = 0;
560 int bSeenLt = 0;
561 int bSeenMatch = 0;
562 int bSeenRank = 0;
565 assert( SQLITE_INDEX_CONSTRAINT_EQ<SQLITE_INDEX_CONSTRAINT_MATCH );
566 assert( SQLITE_INDEX_CONSTRAINT_GT<SQLITE_INDEX_CONSTRAINT_MATCH );
567 assert( SQLITE_INDEX_CONSTRAINT_LE<SQLITE_INDEX_CONSTRAINT_MATCH );
568 assert( SQLITE_INDEX_CONSTRAINT_GE<SQLITE_INDEX_CONSTRAINT_MATCH );
569 assert( SQLITE_INDEX_CONSTRAINT_LE<SQLITE_INDEX_CONSTRAINT_MATCH );
571 if( pConfig->bLock ){
572 pTab->base.zErrMsg = sqlite3_mprintf(
573 "recursively defined fts5 content table"
575 return SQLITE_ERROR;
578 idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 8 + 1);
579 if( idxStr==0 ) return SQLITE_NOMEM;
580 pInfo->idxStr = idxStr;
581 pInfo->needToFreeIdxStr = 1;
583 for(i=0; i<pInfo->nConstraint; i++){
584 struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
585 int iCol = p->iColumn;
586 if( p->op==SQLITE_INDEX_CONSTRAINT_MATCH
587 || (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol>=nCol)
589 /* A MATCH operator or equivalent */
590 if( p->usable==0 || iCol<0 ){
591 /* As there exists an unusable MATCH constraint this is an
592 ** unusable plan. Set a prohibitively high cost. */
593 pInfo->estimatedCost = 1e50;
594 assert( iIdxStr < pInfo->nConstraint*6 + 1 );
595 idxStr[iIdxStr] = 0;
596 return SQLITE_OK;
597 }else{
598 if( iCol==nCol+1 ){
599 if( bSeenRank ) continue;
600 idxStr[iIdxStr++] = 'r';
601 bSeenRank = 1;
602 }else if( iCol>=0 ){
603 bSeenMatch = 1;
604 idxStr[iIdxStr++] = 'M';
605 sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
606 idxStr += strlen(&idxStr[iIdxStr]);
607 assert( idxStr[iIdxStr]=='\0' );
609 pInfo->aConstraintUsage[i].argvIndex = ++iCons;
610 pInfo->aConstraintUsage[i].omit = 1;
612 }else if( p->usable ){
613 if( iCol>=0 && iCol<nCol && fts5UsePatternMatch(pConfig, p) ){
614 assert( p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB );
615 idxStr[iIdxStr++] = p->op==FTS5_PATTERN_LIKE ? 'L' : 'G';
616 sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
617 idxStr += strlen(&idxStr[iIdxStr]);
618 pInfo->aConstraintUsage[i].argvIndex = ++iCons;
619 assert( idxStr[iIdxStr]=='\0' );
620 }else if( bSeenEq==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 ){
621 idxStr[iIdxStr++] = '=';
622 bSeenEq = 1;
623 pInfo->aConstraintUsage[i].argvIndex = ++iCons;
628 if( bSeenEq==0 ){
629 for(i=0; i<pInfo->nConstraint; i++){
630 struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
631 if( p->iColumn<0 && p->usable ){
632 int op = p->op;
633 if( op==SQLITE_INDEX_CONSTRAINT_LT || op==SQLITE_INDEX_CONSTRAINT_LE ){
634 if( bSeenLt ) continue;
635 idxStr[iIdxStr++] = '<';
636 pInfo->aConstraintUsage[i].argvIndex = ++iCons;
637 bSeenLt = 1;
638 }else
639 if( op==SQLITE_INDEX_CONSTRAINT_GT || op==SQLITE_INDEX_CONSTRAINT_GE ){
640 if( bSeenGt ) continue;
641 idxStr[iIdxStr++] = '>';
642 pInfo->aConstraintUsage[i].argvIndex = ++iCons;
643 bSeenGt = 1;
648 idxStr[iIdxStr] = '\0';
650 /* Set idxFlags flags for the ORDER BY clause */
651 if( pInfo->nOrderBy==1 ){
652 int iSort = pInfo->aOrderBy[0].iColumn;
653 if( iSort==(pConfig->nCol+1) && bSeenMatch ){
654 idxFlags |= FTS5_BI_ORDER_RANK;
655 }else if( iSort==-1 ){
656 idxFlags |= FTS5_BI_ORDER_ROWID;
658 if( BitFlagTest(idxFlags, FTS5_BI_ORDER_RANK|FTS5_BI_ORDER_ROWID) ){
659 pInfo->orderByConsumed = 1;
660 if( pInfo->aOrderBy[0].desc ){
661 idxFlags |= FTS5_BI_ORDER_DESC;
666 /* Calculate the estimated cost based on the flags set in idxFlags. */
667 if( bSeenEq ){
668 pInfo->estimatedCost = bSeenMatch ? 100.0 : 10.0;
669 if( bSeenMatch==0 ) fts5SetUniqueFlag(pInfo);
670 }else if( bSeenLt && bSeenGt ){
671 pInfo->estimatedCost = bSeenMatch ? 500.0 : 250000.0;
672 }else if( bSeenLt || bSeenGt ){
673 pInfo->estimatedCost = bSeenMatch ? 750.0 : 750000.0;
674 }else{
675 pInfo->estimatedCost = bSeenMatch ? 1000.0 : 1000000.0;
678 pInfo->idxNum = idxFlags;
679 return SQLITE_OK;
682 static int fts5NewTransaction(Fts5FullTable *pTab){
683 Fts5Cursor *pCsr;
684 for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
685 if( pCsr->base.pVtab==(sqlite3_vtab*)pTab ) return SQLITE_OK;
687 return sqlite3Fts5StorageReset(pTab->pStorage);
691 ** Implementation of xOpen method.
693 static int fts5OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
694 Fts5FullTable *pTab = (Fts5FullTable*)pVTab;
695 Fts5Config *pConfig = pTab->p.pConfig;
696 Fts5Cursor *pCsr = 0; /* New cursor object */
697 sqlite3_int64 nByte; /* Bytes of space to allocate */
698 int rc; /* Return code */
700 rc = fts5NewTransaction(pTab);
701 if( rc==SQLITE_OK ){
702 nByte = sizeof(Fts5Cursor) + pConfig->nCol * sizeof(int);
703 pCsr = (Fts5Cursor*)sqlite3_malloc64(nByte);
704 if( pCsr ){
705 Fts5Global *pGlobal = pTab->pGlobal;
706 memset(pCsr, 0, (size_t)nByte);
707 pCsr->aColumnSize = (int*)&pCsr[1];
708 pCsr->pNext = pGlobal->pCsr;
709 pGlobal->pCsr = pCsr;
710 pCsr->iCsrId = ++pGlobal->iNextId;
711 }else{
712 rc = SQLITE_NOMEM;
715 *ppCsr = (sqlite3_vtab_cursor*)pCsr;
716 return rc;
719 static int fts5StmtType(Fts5Cursor *pCsr){
720 if( pCsr->ePlan==FTS5_PLAN_SCAN ){
721 return (pCsr->bDesc) ? FTS5_STMT_SCAN_DESC : FTS5_STMT_SCAN_ASC;
723 return FTS5_STMT_LOOKUP;
727 ** This function is called after the cursor passed as the only argument
728 ** is moved to point at a different row. It clears all cached data
729 ** specific to the previous row stored by the cursor object.
731 static void fts5CsrNewrow(Fts5Cursor *pCsr){
732 CsrFlagSet(pCsr,
733 FTS5CSR_REQUIRE_CONTENT
734 | FTS5CSR_REQUIRE_DOCSIZE
735 | FTS5CSR_REQUIRE_INST
736 | FTS5CSR_REQUIRE_POSLIST
740 static void fts5FreeCursorComponents(Fts5Cursor *pCsr){
741 Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
742 Fts5Auxdata *pData;
743 Fts5Auxdata *pNext;
745 sqlite3_free(pCsr->aInstIter);
746 sqlite3_free(pCsr->aInst);
747 if( pCsr->pStmt ){
748 int eStmt = fts5StmtType(pCsr);
749 sqlite3Fts5StorageStmtRelease(pTab->pStorage, eStmt, pCsr->pStmt);
751 if( pCsr->pSorter ){
752 Fts5Sorter *pSorter = pCsr->pSorter;
753 sqlite3_finalize(pSorter->pStmt);
754 sqlite3_free(pSorter);
757 if( pCsr->ePlan!=FTS5_PLAN_SOURCE ){
758 sqlite3Fts5ExprFree(pCsr->pExpr);
761 for(pData=pCsr->pAuxdata; pData; pData=pNext){
762 pNext = pData->pNext;
763 if( pData->xDelete ) pData->xDelete(pData->pPtr);
764 sqlite3_free(pData);
767 sqlite3_finalize(pCsr->pRankArgStmt);
768 sqlite3_free(pCsr->apRankArg);
770 if( CsrFlagTest(pCsr, FTS5CSR_FREE_ZRANK) ){
771 sqlite3_free(pCsr->zRank);
772 sqlite3_free(pCsr->zRankArgs);
775 sqlite3Fts5IndexCloseReader(pTab->p.pIndex);
776 memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan - (u8*)pCsr));
781 ** Close the cursor. For additional information see the documentation
782 ** on the xClose method of the virtual table interface.
784 static int fts5CloseMethod(sqlite3_vtab_cursor *pCursor){
785 if( pCursor ){
786 Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab);
787 Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
788 Fts5Cursor **pp;
790 fts5FreeCursorComponents(pCsr);
791 /* Remove the cursor from the Fts5Global.pCsr list */
792 for(pp=&pTab->pGlobal->pCsr; (*pp)!=pCsr; pp=&(*pp)->pNext);
793 *pp = pCsr->pNext;
795 sqlite3_free(pCsr);
797 return SQLITE_OK;
800 static int fts5SorterNext(Fts5Cursor *pCsr){
801 Fts5Sorter *pSorter = pCsr->pSorter;
802 int rc;
804 rc = sqlite3_step(pSorter->pStmt);
805 if( rc==SQLITE_DONE ){
806 rc = SQLITE_OK;
807 CsrFlagSet(pCsr, FTS5CSR_EOF|FTS5CSR_REQUIRE_CONTENT);
808 }else if( rc==SQLITE_ROW ){
809 const u8 *a;
810 const u8 *aBlob;
811 int nBlob;
812 int i;
813 int iOff = 0;
814 rc = SQLITE_OK;
816 pSorter->iRowid = sqlite3_column_int64(pSorter->pStmt, 0);
817 nBlob = sqlite3_column_bytes(pSorter->pStmt, 1);
818 aBlob = a = sqlite3_column_blob(pSorter->pStmt, 1);
820 /* nBlob==0 in detail=none mode. */
821 if( nBlob>0 ){
822 for(i=0; i<(pSorter->nIdx-1); i++){
823 int iVal;
824 a += fts5GetVarint32(a, iVal);
825 iOff += iVal;
826 pSorter->aIdx[i] = iOff;
828 pSorter->aIdx[i] = &aBlob[nBlob] - a;
829 pSorter->aPoslist = a;
832 fts5CsrNewrow(pCsr);
835 return rc;
840 ** Set the FTS5CSR_REQUIRE_RESEEK flag on all FTS5_PLAN_MATCH cursors
841 ** open on table pTab.
843 static void fts5TripCursors(Fts5FullTable *pTab){
844 Fts5Cursor *pCsr;
845 for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
846 if( pCsr->ePlan==FTS5_PLAN_MATCH
847 && pCsr->base.pVtab==(sqlite3_vtab*)pTab
849 CsrFlagSet(pCsr, FTS5CSR_REQUIRE_RESEEK);
855 ** If the REQUIRE_RESEEK flag is set on the cursor passed as the first
856 ** argument, close and reopen all Fts5IndexIter iterators that the cursor
857 ** is using. Then attempt to move the cursor to a rowid equal to or laster
858 ** (in the cursors sort order - ASC or DESC) than the current rowid.
860 ** If the new rowid is not equal to the old, set output parameter *pbSkip
861 ** to 1 before returning. Otherwise, leave it unchanged.
863 ** Return SQLITE_OK if successful or if no reseek was required, or an
864 ** error code if an error occurred.
866 static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){
867 int rc = SQLITE_OK;
868 assert( *pbSkip==0 );
869 if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_RESEEK) ){
870 Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
871 int bDesc = pCsr->bDesc;
872 i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr);
874 rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->p.pIndex, iRowid, bDesc);
875 if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){
876 *pbSkip = 1;
879 CsrFlagClear(pCsr, FTS5CSR_REQUIRE_RESEEK);
880 fts5CsrNewrow(pCsr);
881 if( sqlite3Fts5ExprEof(pCsr->pExpr) ){
882 CsrFlagSet(pCsr, FTS5CSR_EOF);
883 *pbSkip = 1;
886 return rc;
891 ** Advance the cursor to the next row in the table that matches the
892 ** search criteria.
894 ** Return SQLITE_OK if nothing goes wrong. SQLITE_OK is returned
895 ** even if we reach end-of-file. The fts5EofMethod() will be called
896 ** subsequently to determine whether or not an EOF was hit.
898 static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){
899 Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
900 int rc;
902 assert( (pCsr->ePlan<3)==
903 (pCsr->ePlan==FTS5_PLAN_MATCH || pCsr->ePlan==FTS5_PLAN_SOURCE)
905 assert( !CsrFlagTest(pCsr, FTS5CSR_EOF) );
907 if( pCsr->ePlan<3 ){
908 int bSkip = 0;
909 if( (rc = fts5CursorReseek(pCsr, &bSkip)) || bSkip ) return rc;
910 rc = sqlite3Fts5ExprNext(pCsr->pExpr, pCsr->iLastRowid);
911 CsrFlagSet(pCsr, sqlite3Fts5ExprEof(pCsr->pExpr));
912 fts5CsrNewrow(pCsr);
913 }else{
914 switch( pCsr->ePlan ){
915 case FTS5_PLAN_SPECIAL: {
916 CsrFlagSet(pCsr, FTS5CSR_EOF);
917 rc = SQLITE_OK;
918 break;
921 case FTS5_PLAN_SORTED_MATCH: {
922 rc = fts5SorterNext(pCsr);
923 break;
926 default: {
927 Fts5Config *pConfig = ((Fts5Table*)pCursor->pVtab)->pConfig;
928 pConfig->bLock++;
929 rc = sqlite3_step(pCsr->pStmt);
930 pConfig->bLock--;
931 if( rc!=SQLITE_ROW ){
932 CsrFlagSet(pCsr, FTS5CSR_EOF);
933 rc = sqlite3_reset(pCsr->pStmt);
934 if( rc!=SQLITE_OK ){
935 pCursor->pVtab->zErrMsg = sqlite3_mprintf(
936 "%s", sqlite3_errmsg(pConfig->db)
939 }else{
940 rc = SQLITE_OK;
942 break;
947 return rc;
951 static int fts5PrepareStatement(
952 sqlite3_stmt **ppStmt,
953 Fts5Config *pConfig,
954 const char *zFmt,
957 sqlite3_stmt *pRet = 0;
958 int rc;
959 char *zSql;
960 va_list ap;
962 va_start(ap, zFmt);
963 zSql = sqlite3_vmprintf(zFmt, ap);
964 if( zSql==0 ){
965 rc = SQLITE_NOMEM;
966 }else{
967 rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
968 SQLITE_PREPARE_PERSISTENT, &pRet, 0);
969 if( rc!=SQLITE_OK ){
970 *pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db));
972 sqlite3_free(zSql);
975 va_end(ap);
976 *ppStmt = pRet;
977 return rc;
980 static int fts5CursorFirstSorted(
981 Fts5FullTable *pTab,
982 Fts5Cursor *pCsr,
983 int bDesc
985 Fts5Config *pConfig = pTab->p.pConfig;
986 Fts5Sorter *pSorter;
987 int nPhrase;
988 sqlite3_int64 nByte;
989 int rc;
990 const char *zRank = pCsr->zRank;
991 const char *zRankArgs = pCsr->zRankArgs;
993 nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
994 nByte = sizeof(Fts5Sorter) + sizeof(int) * (nPhrase-1);
995 pSorter = (Fts5Sorter*)sqlite3_malloc64(nByte);
996 if( pSorter==0 ) return SQLITE_NOMEM;
997 memset(pSorter, 0, (size_t)nByte);
998 pSorter->nIdx = nPhrase;
1000 /* TODO: It would be better to have some system for reusing statement
1001 ** handles here, rather than preparing a new one for each query. But that
1002 ** is not possible as SQLite reference counts the virtual table objects.
1003 ** And since the statement required here reads from this very virtual
1004 ** table, saving it creates a circular reference.
1006 ** If SQLite a built-in statement cache, this wouldn't be a problem. */
1007 rc = fts5PrepareStatement(&pSorter->pStmt, pConfig,
1008 "SELECT rowid, rank FROM %Q.%Q ORDER BY %s(\"%w\"%s%s) %s",
1009 pConfig->zDb, pConfig->zName, zRank, pConfig->zName,
1010 (zRankArgs ? ", " : ""),
1011 (zRankArgs ? zRankArgs : ""),
1012 bDesc ? "DESC" : "ASC"
1015 pCsr->pSorter = pSorter;
1016 if( rc==SQLITE_OK ){
1017 assert( pTab->pSortCsr==0 );
1018 pTab->pSortCsr = pCsr;
1019 rc = fts5SorterNext(pCsr);
1020 pTab->pSortCsr = 0;
1023 if( rc!=SQLITE_OK ){
1024 sqlite3_finalize(pSorter->pStmt);
1025 sqlite3_free(pSorter);
1026 pCsr->pSorter = 0;
1029 return rc;
1032 static int fts5CursorFirst(Fts5FullTable *pTab, Fts5Cursor *pCsr, int bDesc){
1033 int rc;
1034 Fts5Expr *pExpr = pCsr->pExpr;
1035 rc = sqlite3Fts5ExprFirst(pExpr, pTab->p.pIndex, pCsr->iFirstRowid, bDesc);
1036 if( sqlite3Fts5ExprEof(pExpr) ){
1037 CsrFlagSet(pCsr, FTS5CSR_EOF);
1039 fts5CsrNewrow(pCsr);
1040 return rc;
1044 ** Process a "special" query. A special query is identified as one with a
1045 ** MATCH expression that begins with a '*' character. The remainder of
1046 ** the text passed to the MATCH operator are used as the special query
1047 ** parameters.
1049 static int fts5SpecialMatch(
1050 Fts5FullTable *pTab,
1051 Fts5Cursor *pCsr,
1052 const char *zQuery
1054 int rc = SQLITE_OK; /* Return code */
1055 const char *z = zQuery; /* Special query text */
1056 int n; /* Number of bytes in text at z */
1058 while( z[0]==' ' ) z++;
1059 for(n=0; z[n] && z[n]!=' '; n++);
1061 assert( pTab->p.base.zErrMsg==0 );
1062 pCsr->ePlan = FTS5_PLAN_SPECIAL;
1064 if( n==5 && 0==sqlite3_strnicmp("reads", z, n) ){
1065 pCsr->iSpecial = sqlite3Fts5IndexReads(pTab->p.pIndex);
1067 else if( n==2 && 0==sqlite3_strnicmp("id", z, n) ){
1068 pCsr->iSpecial = pCsr->iCsrId;
1070 else{
1071 /* An unrecognized directive. Return an error message. */
1072 pTab->p.base.zErrMsg = sqlite3_mprintf("unknown special query: %.*s", n, z);
1073 rc = SQLITE_ERROR;
1076 return rc;
1080 ** Search for an auxiliary function named zName that can be used with table
1081 ** pTab. If one is found, return a pointer to the corresponding Fts5Auxiliary
1082 ** structure. Otherwise, if no such function exists, return NULL.
1084 static Fts5Auxiliary *fts5FindAuxiliary(Fts5FullTable *pTab, const char *zName){
1085 Fts5Auxiliary *pAux;
1087 for(pAux=pTab->pGlobal->pAux; pAux; pAux=pAux->pNext){
1088 if( sqlite3_stricmp(zName, pAux->zFunc)==0 ) return pAux;
1091 /* No function of the specified name was found. Return 0. */
1092 return 0;
1096 static int fts5FindRankFunction(Fts5Cursor *pCsr){
1097 Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
1098 Fts5Config *pConfig = pTab->p.pConfig;
1099 int rc = SQLITE_OK;
1100 Fts5Auxiliary *pAux = 0;
1101 const char *zRank = pCsr->zRank;
1102 const char *zRankArgs = pCsr->zRankArgs;
1104 if( zRankArgs ){
1105 char *zSql = sqlite3Fts5Mprintf(&rc, "SELECT %s", zRankArgs);
1106 if( zSql ){
1107 sqlite3_stmt *pStmt = 0;
1108 rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
1109 SQLITE_PREPARE_PERSISTENT, &pStmt, 0);
1110 sqlite3_free(zSql);
1111 assert( rc==SQLITE_OK || pCsr->pRankArgStmt==0 );
1112 if( rc==SQLITE_OK ){
1113 if( SQLITE_ROW==sqlite3_step(pStmt) ){
1114 sqlite3_int64 nByte;
1115 pCsr->nRankArg = sqlite3_column_count(pStmt);
1116 nByte = sizeof(sqlite3_value*)*pCsr->nRankArg;
1117 pCsr->apRankArg = (sqlite3_value**)sqlite3Fts5MallocZero(&rc, nByte);
1118 if( rc==SQLITE_OK ){
1119 int i;
1120 for(i=0; i<pCsr->nRankArg; i++){
1121 pCsr->apRankArg[i] = sqlite3_column_value(pStmt, i);
1124 pCsr->pRankArgStmt = pStmt;
1125 }else{
1126 rc = sqlite3_finalize(pStmt);
1127 assert( rc!=SQLITE_OK );
1133 if( rc==SQLITE_OK ){
1134 pAux = fts5FindAuxiliary(pTab, zRank);
1135 if( pAux==0 ){
1136 assert( pTab->p.base.zErrMsg==0 );
1137 pTab->p.base.zErrMsg = sqlite3_mprintf("no such function: %s", zRank);
1138 rc = SQLITE_ERROR;
1142 pCsr->pRank = pAux;
1143 return rc;
1147 static int fts5CursorParseRank(
1148 Fts5Config *pConfig,
1149 Fts5Cursor *pCsr,
1150 sqlite3_value *pRank
1152 int rc = SQLITE_OK;
1153 if( pRank ){
1154 const char *z = (const char*)sqlite3_value_text(pRank);
1155 char *zRank = 0;
1156 char *zRankArgs = 0;
1158 if( z==0 ){
1159 if( sqlite3_value_type(pRank)==SQLITE_NULL ) rc = SQLITE_ERROR;
1160 }else{
1161 rc = sqlite3Fts5ConfigParseRank(z, &zRank, &zRankArgs);
1163 if( rc==SQLITE_OK ){
1164 pCsr->zRank = zRank;
1165 pCsr->zRankArgs = zRankArgs;
1166 CsrFlagSet(pCsr, FTS5CSR_FREE_ZRANK);
1167 }else if( rc==SQLITE_ERROR ){
1168 pCsr->base.pVtab->zErrMsg = sqlite3_mprintf(
1169 "parse error in rank function: %s", z
1172 }else{
1173 if( pConfig->zRank ){
1174 pCsr->zRank = (char*)pConfig->zRank;
1175 pCsr->zRankArgs = (char*)pConfig->zRankArgs;
1176 }else{
1177 pCsr->zRank = (char*)FTS5_DEFAULT_RANK;
1178 pCsr->zRankArgs = 0;
1181 return rc;
1184 static i64 fts5GetRowidLimit(sqlite3_value *pVal, i64 iDefault){
1185 if( pVal ){
1186 int eType = sqlite3_value_numeric_type(pVal);
1187 if( eType==SQLITE_INTEGER ){
1188 return sqlite3_value_int64(pVal);
1191 return iDefault;
1195 ** This is the xFilter interface for the virtual table. See
1196 ** the virtual table xFilter method documentation for additional
1197 ** information.
1199 ** There are three possible query strategies:
1201 ** 1. Full-text search using a MATCH operator.
1202 ** 2. A by-rowid lookup.
1203 ** 3. A full-table scan.
1205 static int fts5FilterMethod(
1206 sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
1207 int idxNum, /* Strategy index */
1208 const char *idxStr, /* Unused */
1209 int nVal, /* Number of elements in apVal */
1210 sqlite3_value **apVal /* Arguments for the indexing scheme */
1212 Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab);
1213 Fts5Config *pConfig = pTab->p.pConfig;
1214 Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
1215 int rc = SQLITE_OK; /* Error code */
1216 int bDesc; /* True if ORDER BY [rank|rowid] DESC */
1217 int bOrderByRank; /* True if ORDER BY rank */
1218 sqlite3_value *pRank = 0; /* rank MATCH ? expression (or NULL) */
1219 sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */
1220 sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */
1221 sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */
1222 int iCol; /* Column on LHS of MATCH operator */
1223 char **pzErrmsg = pConfig->pzErrmsg;
1224 int i;
1225 int iIdxStr = 0;
1226 Fts5Expr *pExpr = 0;
1228 if( pConfig->bLock ){
1229 pTab->p.base.zErrMsg = sqlite3_mprintf(
1230 "recursively defined fts5 content table"
1232 return SQLITE_ERROR;
1235 if( pCsr->ePlan ){
1236 fts5FreeCursorComponents(pCsr);
1237 memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan-(u8*)pCsr));
1240 assert( pCsr->pStmt==0 );
1241 assert( pCsr->pExpr==0 );
1242 assert( pCsr->csrflags==0 );
1243 assert( pCsr->pRank==0 );
1244 assert( pCsr->zRank==0 );
1245 assert( pCsr->zRankArgs==0 );
1246 assert( pTab->pSortCsr==0 || nVal==0 );
1248 assert( pzErrmsg==0 || pzErrmsg==&pTab->p.base.zErrMsg );
1249 pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
1251 /* Decode the arguments passed through to this function. */
1252 for(i=0; i<nVal; i++){
1253 switch( idxStr[iIdxStr++] ){
1254 case 'r':
1255 pRank = apVal[i];
1256 break;
1257 case 'M': {
1258 const char *zText = (const char*)sqlite3_value_text(apVal[i]);
1259 if( zText==0 ) zText = "";
1260 iCol = 0;
1262 iCol = iCol*10 + (idxStr[iIdxStr]-'0');
1263 iIdxStr++;
1264 }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
1266 if( zText[0]=='*' ){
1267 /* The user has issued a query of the form "MATCH '*...'". This
1268 ** indicates that the MATCH expression is not a full text query,
1269 ** but a request for an internal parameter. */
1270 rc = fts5SpecialMatch(pTab, pCsr, &zText[1]);
1271 goto filter_out;
1272 }else{
1273 char **pzErr = &pTab->p.base.zErrMsg;
1274 rc = sqlite3Fts5ExprNew(pConfig, 0, iCol, zText, &pExpr, pzErr);
1275 if( rc==SQLITE_OK ){
1276 rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
1277 pExpr = 0;
1279 if( rc!=SQLITE_OK ) goto filter_out;
1282 break;
1284 case 'L':
1285 case 'G': {
1286 int bGlob = (idxStr[iIdxStr-1]=='G');
1287 const char *zText = (const char*)sqlite3_value_text(apVal[i]);
1288 iCol = 0;
1290 iCol = iCol*10 + (idxStr[iIdxStr]-'0');
1291 iIdxStr++;
1292 }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
1293 if( zText ){
1294 rc = sqlite3Fts5ExprPattern(pConfig, bGlob, iCol, zText, &pExpr);
1296 if( rc==SQLITE_OK ){
1297 rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
1298 pExpr = 0;
1300 if( rc!=SQLITE_OK ) goto filter_out;
1301 break;
1303 case '=':
1304 pRowidEq = apVal[i];
1305 break;
1306 case '<':
1307 pRowidLe = apVal[i];
1308 break;
1309 default: assert( idxStr[iIdxStr-1]=='>' );
1310 pRowidGe = apVal[i];
1311 break;
1314 bOrderByRank = ((idxNum & FTS5_BI_ORDER_RANK) ? 1 : 0);
1315 pCsr->bDesc = bDesc = ((idxNum & FTS5_BI_ORDER_DESC) ? 1 : 0);
1317 /* Set the cursor upper and lower rowid limits. Only some strategies
1318 ** actually use them. This is ok, as the xBestIndex() method leaves the
1319 ** sqlite3_index_constraint.omit flag clear for range constraints
1320 ** on the rowid field. */
1321 if( pRowidEq ){
1322 pRowidLe = pRowidGe = pRowidEq;
1324 if( bDesc ){
1325 pCsr->iFirstRowid = fts5GetRowidLimit(pRowidLe, LARGEST_INT64);
1326 pCsr->iLastRowid = fts5GetRowidLimit(pRowidGe, SMALLEST_INT64);
1327 }else{
1328 pCsr->iLastRowid = fts5GetRowidLimit(pRowidLe, LARGEST_INT64);
1329 pCsr->iFirstRowid = fts5GetRowidLimit(pRowidGe, SMALLEST_INT64);
1332 if( pTab->pSortCsr ){
1333 /* If pSortCsr is non-NULL, then this call is being made as part of
1334 ** processing for a "... MATCH <expr> ORDER BY rank" query (ePlan is
1335 ** set to FTS5_PLAN_SORTED_MATCH). pSortCsr is the cursor that will
1336 ** return results to the user for this query. The current cursor
1337 ** (pCursor) is used to execute the query issued by function
1338 ** fts5CursorFirstSorted() above. */
1339 assert( pRowidEq==0 && pRowidLe==0 && pRowidGe==0 && pRank==0 );
1340 assert( nVal==0 && bOrderByRank==0 && bDesc==0 );
1341 assert( pCsr->iLastRowid==LARGEST_INT64 );
1342 assert( pCsr->iFirstRowid==SMALLEST_INT64 );
1343 if( pTab->pSortCsr->bDesc ){
1344 pCsr->iLastRowid = pTab->pSortCsr->iFirstRowid;
1345 pCsr->iFirstRowid = pTab->pSortCsr->iLastRowid;
1346 }else{
1347 pCsr->iLastRowid = pTab->pSortCsr->iLastRowid;
1348 pCsr->iFirstRowid = pTab->pSortCsr->iFirstRowid;
1350 pCsr->ePlan = FTS5_PLAN_SOURCE;
1351 pCsr->pExpr = pTab->pSortCsr->pExpr;
1352 rc = fts5CursorFirst(pTab, pCsr, bDesc);
1353 }else if( pCsr->pExpr ){
1354 rc = fts5CursorParseRank(pConfig, pCsr, pRank);
1355 if( rc==SQLITE_OK ){
1356 if( bOrderByRank ){
1357 pCsr->ePlan = FTS5_PLAN_SORTED_MATCH;
1358 rc = fts5CursorFirstSorted(pTab, pCsr, bDesc);
1359 }else{
1360 pCsr->ePlan = FTS5_PLAN_MATCH;
1361 rc = fts5CursorFirst(pTab, pCsr, bDesc);
1364 }else if( pConfig->zContent==0 ){
1365 *pConfig->pzErrmsg = sqlite3_mprintf(
1366 "%s: table does not support scanning", pConfig->zName
1368 rc = SQLITE_ERROR;
1369 }else{
1370 /* This is either a full-table scan (ePlan==FTS5_PLAN_SCAN) or a lookup
1371 ** by rowid (ePlan==FTS5_PLAN_ROWID). */
1372 pCsr->ePlan = (pRowidEq ? FTS5_PLAN_ROWID : FTS5_PLAN_SCAN);
1373 rc = sqlite3Fts5StorageStmt(
1374 pTab->pStorage, fts5StmtType(pCsr), &pCsr->pStmt, &pTab->p.base.zErrMsg
1376 if( rc==SQLITE_OK ){
1377 if( pRowidEq!=0 ){
1378 assert( pCsr->ePlan==FTS5_PLAN_ROWID );
1379 sqlite3_bind_value(pCsr->pStmt, 1, pRowidEq);
1380 }else{
1381 sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iFirstRowid);
1382 sqlite3_bind_int64(pCsr->pStmt, 2, pCsr->iLastRowid);
1384 rc = fts5NextMethod(pCursor);
1388 filter_out:
1389 sqlite3Fts5ExprFree(pExpr);
1390 pConfig->pzErrmsg = pzErrmsg;
1391 return rc;
1395 ** This is the xEof method of the virtual table. SQLite calls this
1396 ** routine to find out if it has reached the end of a result set.
1398 static int fts5EofMethod(sqlite3_vtab_cursor *pCursor){
1399 Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
1400 return (CsrFlagTest(pCsr, FTS5CSR_EOF) ? 1 : 0);
1404 ** Return the rowid that the cursor currently points to.
1406 static i64 fts5CursorRowid(Fts5Cursor *pCsr){
1407 assert( pCsr->ePlan==FTS5_PLAN_MATCH
1408 || pCsr->ePlan==FTS5_PLAN_SORTED_MATCH
1409 || pCsr->ePlan==FTS5_PLAN_SOURCE
1411 if( pCsr->pSorter ){
1412 return pCsr->pSorter->iRowid;
1413 }else{
1414 return sqlite3Fts5ExprRowid(pCsr->pExpr);
1419 ** This is the xRowid method. The SQLite core calls this routine to
1420 ** retrieve the rowid for the current row of the result set. fts5
1421 ** exposes %_content.rowid as the rowid for the virtual table. The
1422 ** rowid should be written to *pRowid.
1424 static int fts5RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
1425 Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
1426 int ePlan = pCsr->ePlan;
1428 assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 );
1429 switch( ePlan ){
1430 case FTS5_PLAN_SPECIAL:
1431 *pRowid = 0;
1432 break;
1434 case FTS5_PLAN_SOURCE:
1435 case FTS5_PLAN_MATCH:
1436 case FTS5_PLAN_SORTED_MATCH:
1437 *pRowid = fts5CursorRowid(pCsr);
1438 break;
1440 default:
1441 *pRowid = sqlite3_column_int64(pCsr->pStmt, 0);
1442 break;
1445 return SQLITE_OK;
1449 ** If the cursor requires seeking (bSeekRequired flag is set), seek it.
1450 ** Return SQLITE_OK if no error occurs, or an SQLite error code otherwise.
1452 ** If argument bErrormsg is true and an error occurs, an error message may
1453 ** be left in sqlite3_vtab.zErrMsg.
1455 static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){
1456 int rc = SQLITE_OK;
1458 /* If the cursor does not yet have a statement handle, obtain one now. */
1459 if( pCsr->pStmt==0 ){
1460 Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
1461 int eStmt = fts5StmtType(pCsr);
1462 rc = sqlite3Fts5StorageStmt(
1463 pTab->pStorage, eStmt, &pCsr->pStmt, (bErrormsg?&pTab->p.base.zErrMsg:0)
1465 assert( rc!=SQLITE_OK || pTab->p.base.zErrMsg==0 );
1466 assert( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) );
1469 if( rc==SQLITE_OK && CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) ){
1470 Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
1471 assert( pCsr->pExpr );
1472 sqlite3_reset(pCsr->pStmt);
1473 sqlite3_bind_int64(pCsr->pStmt, 1, fts5CursorRowid(pCsr));
1474 pTab->pConfig->bLock++;
1475 rc = sqlite3_step(pCsr->pStmt);
1476 pTab->pConfig->bLock--;
1477 if( rc==SQLITE_ROW ){
1478 rc = SQLITE_OK;
1479 CsrFlagClear(pCsr, FTS5CSR_REQUIRE_CONTENT);
1480 }else{
1481 rc = sqlite3_reset(pCsr->pStmt);
1482 if( rc==SQLITE_OK ){
1483 rc = FTS5_CORRUPT;
1484 }else if( pTab->pConfig->pzErrmsg ){
1485 *pTab->pConfig->pzErrmsg = sqlite3_mprintf(
1486 "%s", sqlite3_errmsg(pTab->pConfig->db)
1491 return rc;
1494 static void fts5SetVtabError(Fts5FullTable *p, const char *zFormat, ...){
1495 va_list ap; /* ... printf arguments */
1496 va_start(ap, zFormat);
1497 assert( p->p.base.zErrMsg==0 );
1498 p->p.base.zErrMsg = sqlite3_vmprintf(zFormat, ap);
1499 va_end(ap);
1503 ** This function is called to handle an FTS INSERT command. In other words,
1504 ** an INSERT statement of the form:
1506 ** INSERT INTO fts(fts) VALUES($pCmd)
1507 ** INSERT INTO fts(fts, rank) VALUES($pCmd, $pVal)
1509 ** Argument pVal is the value assigned to column "fts" by the INSERT
1510 ** statement. This function returns SQLITE_OK if successful, or an SQLite
1511 ** error code if an error occurs.
1513 ** The commands implemented by this function are documented in the "Special
1514 ** INSERT Directives" section of the documentation. It should be updated if
1515 ** more commands are added to this function.
1517 static int fts5SpecialInsert(
1518 Fts5FullTable *pTab, /* Fts5 table object */
1519 const char *zCmd, /* Text inserted into table-name column */
1520 sqlite3_value *pVal /* Value inserted into rank column */
1522 Fts5Config *pConfig = pTab->p.pConfig;
1523 int rc = SQLITE_OK;
1524 int bError = 0;
1526 if( 0==sqlite3_stricmp("delete-all", zCmd) ){
1527 if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
1528 fts5SetVtabError(pTab,
1529 "'delete-all' may only be used with a "
1530 "contentless or external content fts5 table"
1532 rc = SQLITE_ERROR;
1533 }else{
1534 rc = sqlite3Fts5StorageDeleteAll(pTab->pStorage);
1536 }else if( 0==sqlite3_stricmp("rebuild", zCmd) ){
1537 if( pConfig->eContent==FTS5_CONTENT_NONE ){
1538 fts5SetVtabError(pTab,
1539 "'rebuild' may not be used with a contentless fts5 table"
1541 rc = SQLITE_ERROR;
1542 }else{
1543 rc = sqlite3Fts5StorageRebuild(pTab->pStorage);
1545 }else if( 0==sqlite3_stricmp("optimize", zCmd) ){
1546 rc = sqlite3Fts5StorageOptimize(pTab->pStorage);
1547 }else if( 0==sqlite3_stricmp("merge", zCmd) ){
1548 int nMerge = sqlite3_value_int(pVal);
1549 rc = sqlite3Fts5StorageMerge(pTab->pStorage, nMerge);
1550 }else if( 0==sqlite3_stricmp("integrity-check", zCmd) ){
1551 int iArg = sqlite3_value_int(pVal);
1552 rc = sqlite3Fts5StorageIntegrity(pTab->pStorage, iArg);
1553 #ifdef SQLITE_DEBUG
1554 }else if( 0==sqlite3_stricmp("prefix-index", zCmd) ){
1555 pConfig->bPrefixIndex = sqlite3_value_int(pVal);
1556 #endif
1557 }else{
1558 rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
1559 if( rc==SQLITE_OK ){
1560 rc = sqlite3Fts5ConfigSetValue(pTab->p.pConfig, zCmd, pVal, &bError);
1562 if( rc==SQLITE_OK ){
1563 if( bError ){
1564 rc = SQLITE_ERROR;
1565 }else{
1566 rc = sqlite3Fts5StorageConfigValue(pTab->pStorage, zCmd, pVal, 0);
1570 return rc;
1573 static int fts5SpecialDelete(
1574 Fts5FullTable *pTab,
1575 sqlite3_value **apVal
1577 int rc = SQLITE_OK;
1578 int eType1 = sqlite3_value_type(apVal[1]);
1579 if( eType1==SQLITE_INTEGER ){
1580 sqlite3_int64 iDel = sqlite3_value_int64(apVal[1]);
1581 rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, &apVal[2]);
1583 return rc;
1586 static void fts5StorageInsert(
1587 int *pRc,
1588 Fts5FullTable *pTab,
1589 sqlite3_value **apVal,
1590 i64 *piRowid
1592 int rc = *pRc;
1593 if( rc==SQLITE_OK ){
1594 rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, piRowid);
1596 if( rc==SQLITE_OK ){
1597 rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *piRowid);
1599 *pRc = rc;
1603 ** This function is the implementation of the xUpdate callback used by
1604 ** FTS3 virtual tables. It is invoked by SQLite each time a row is to be
1605 ** inserted, updated or deleted.
1607 ** A delete specifies a single argument - the rowid of the row to remove.
1609 ** Update and insert operations pass:
1611 ** 1. The "old" rowid, or NULL.
1612 ** 2. The "new" rowid.
1613 ** 3. Values for each of the nCol matchable columns.
1614 ** 4. Values for the two hidden columns (<tablename> and "rank").
1616 static int fts5UpdateMethod(
1617 sqlite3_vtab *pVtab, /* Virtual table handle */
1618 int nArg, /* Size of argument array */
1619 sqlite3_value **apVal, /* Array of arguments */
1620 sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */
1622 Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
1623 Fts5Config *pConfig = pTab->p.pConfig;
1624 int eType0; /* value_type() of apVal[0] */
1625 int rc = SQLITE_OK; /* Return code */
1627 /* A transaction must be open when this is called. */
1628 assert( pTab->ts.eState==1 || pTab->ts.eState==2 );
1630 assert( pVtab->zErrMsg==0 );
1631 assert( nArg==1 || nArg==(2+pConfig->nCol+2) );
1632 assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER
1633 || sqlite3_value_type(apVal[0])==SQLITE_NULL
1635 assert( pTab->p.pConfig->pzErrmsg==0 );
1636 pTab->p.pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
1638 /* Put any active cursors into REQUIRE_SEEK state. */
1639 fts5TripCursors(pTab);
1641 eType0 = sqlite3_value_type(apVal[0]);
1642 if( eType0==SQLITE_NULL
1643 && sqlite3_value_type(apVal[2+pConfig->nCol])!=SQLITE_NULL
1645 /* A "special" INSERT op. These are handled separately. */
1646 const char *z = (const char*)sqlite3_value_text(apVal[2+pConfig->nCol]);
1647 if( pConfig->eContent!=FTS5_CONTENT_NORMAL
1648 && 0==sqlite3_stricmp("delete", z)
1650 rc = fts5SpecialDelete(pTab, apVal);
1651 }else{
1652 rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]);
1654 }else{
1655 /* A regular INSERT, UPDATE or DELETE statement. The trick here is that
1656 ** any conflict on the rowid value must be detected before any
1657 ** modifications are made to the database file. There are 4 cases:
1659 ** 1) DELETE
1660 ** 2) UPDATE (rowid not modified)
1661 ** 3) UPDATE (rowid modified)
1662 ** 4) INSERT
1664 ** Cases 3 and 4 may violate the rowid constraint.
1666 int eConflict = SQLITE_ABORT;
1667 if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
1668 eConflict = sqlite3_vtab_on_conflict(pConfig->db);
1671 assert( eType0==SQLITE_INTEGER || eType0==SQLITE_NULL );
1672 assert( nArg!=1 || eType0==SQLITE_INTEGER );
1674 /* Filter out attempts to run UPDATE or DELETE on contentless tables.
1675 ** This is not suported. */
1676 if( eType0==SQLITE_INTEGER && fts5IsContentless(pTab) ){
1677 pTab->p.base.zErrMsg = sqlite3_mprintf(
1678 "cannot %s contentless fts5 table: %s",
1679 (nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName
1681 rc = SQLITE_ERROR;
1684 /* DELETE */
1685 else if( nArg==1 ){
1686 i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */
1687 rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0);
1690 /* INSERT or UPDATE */
1691 else{
1692 int eType1 = sqlite3_value_numeric_type(apVal[1]);
1694 if( eType1!=SQLITE_INTEGER && eType1!=SQLITE_NULL ){
1695 rc = SQLITE_MISMATCH;
1698 else if( eType0!=SQLITE_INTEGER ){
1699 /* If this is a REPLACE, first remove the current entry (if any) */
1700 if( eConflict==SQLITE_REPLACE && eType1==SQLITE_INTEGER ){
1701 i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */
1702 rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
1704 fts5StorageInsert(&rc, pTab, apVal, pRowid);
1707 /* UPDATE */
1708 else{
1709 i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */
1710 i64 iNew = sqlite3_value_int64(apVal[1]); /* New rowid */
1711 if( eType1==SQLITE_INTEGER && iOld!=iNew ){
1712 if( eConflict==SQLITE_REPLACE ){
1713 rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
1714 if( rc==SQLITE_OK ){
1715 rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
1717 fts5StorageInsert(&rc, pTab, apVal, pRowid);
1718 }else{
1719 rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid);
1720 if( rc==SQLITE_OK ){
1721 rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
1723 if( rc==SQLITE_OK ){
1724 rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal,*pRowid);
1727 }else{
1728 rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
1729 fts5StorageInsert(&rc, pTab, apVal, pRowid);
1735 pTab->p.pConfig->pzErrmsg = 0;
1736 return rc;
1740 ** Implementation of xSync() method.
1742 static int fts5SyncMethod(sqlite3_vtab *pVtab){
1743 int rc;
1744 Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
1745 fts5CheckTransactionState(pTab, FTS5_SYNC, 0);
1746 pTab->p.pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
1747 fts5TripCursors(pTab);
1748 rc = sqlite3Fts5StorageSync(pTab->pStorage);
1749 pTab->p.pConfig->pzErrmsg = 0;
1750 return rc;
1754 ** Implementation of xBegin() method.
1756 static int fts5BeginMethod(sqlite3_vtab *pVtab){
1757 fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_BEGIN, 0);
1758 fts5NewTransaction((Fts5FullTable*)pVtab);
1759 return SQLITE_OK;
1763 ** Implementation of xCommit() method. This is a no-op. The contents of
1764 ** the pending-terms hash-table have already been flushed into the database
1765 ** by fts5SyncMethod().
1767 static int fts5CommitMethod(sqlite3_vtab *pVtab){
1768 UNUSED_PARAM(pVtab); /* Call below is a no-op for NDEBUG builds */
1769 fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_COMMIT, 0);
1770 return SQLITE_OK;
1774 ** Implementation of xRollback(). Discard the contents of the pending-terms
1775 ** hash-table. Any changes made to the database are reverted by SQLite.
1777 static int fts5RollbackMethod(sqlite3_vtab *pVtab){
1778 int rc;
1779 Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
1780 fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0);
1781 rc = sqlite3Fts5StorageRollback(pTab->pStorage);
1782 return rc;
1785 static int fts5CsrPoslist(Fts5Cursor*, int, const u8**, int*);
1787 static void *fts5ApiUserData(Fts5Context *pCtx){
1788 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
1789 return pCsr->pAux->pUserData;
1792 static int fts5ApiColumnCount(Fts5Context *pCtx){
1793 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
1794 return ((Fts5Table*)(pCsr->base.pVtab))->pConfig->nCol;
1797 static int fts5ApiColumnTotalSize(
1798 Fts5Context *pCtx,
1799 int iCol,
1800 sqlite3_int64 *pnToken
1802 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
1803 Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
1804 return sqlite3Fts5StorageSize(pTab->pStorage, iCol, pnToken);
1807 static int fts5ApiRowCount(Fts5Context *pCtx, i64 *pnRow){
1808 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
1809 Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
1810 return sqlite3Fts5StorageRowCount(pTab->pStorage, pnRow);
1813 static int fts5ApiTokenize(
1814 Fts5Context *pCtx,
1815 const char *pText, int nText,
1816 void *pUserData,
1817 int (*xToken)(void*, int, const char*, int, int, int)
1819 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
1820 Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
1821 return sqlite3Fts5Tokenize(
1822 pTab->pConfig, FTS5_TOKENIZE_AUX, pText, nText, pUserData, xToken
1826 static int fts5ApiPhraseCount(Fts5Context *pCtx){
1827 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
1828 return sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
1831 static int fts5ApiPhraseSize(Fts5Context *pCtx, int iPhrase){
1832 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
1833 return sqlite3Fts5ExprPhraseSize(pCsr->pExpr, iPhrase);
1836 static int fts5ApiColumnText(
1837 Fts5Context *pCtx,
1838 int iCol,
1839 const char **pz,
1840 int *pn
1842 int rc = SQLITE_OK;
1843 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
1844 if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab))
1845 || pCsr->ePlan==FTS5_PLAN_SPECIAL
1847 *pz = 0;
1848 *pn = 0;
1849 }else{
1850 rc = fts5SeekCursor(pCsr, 0);
1851 if( rc==SQLITE_OK ){
1852 *pz = (const char*)sqlite3_column_text(pCsr->pStmt, iCol+1);
1853 *pn = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
1856 return rc;
1859 static int fts5CsrPoslist(
1860 Fts5Cursor *pCsr,
1861 int iPhrase,
1862 const u8 **pa,
1863 int *pn
1865 Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
1866 int rc = SQLITE_OK;
1867 int bLive = (pCsr->pSorter==0);
1869 if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){
1871 if( pConfig->eDetail!=FTS5_DETAIL_FULL ){
1872 Fts5PoslistPopulator *aPopulator;
1873 int i;
1874 aPopulator = sqlite3Fts5ExprClearPoslists(pCsr->pExpr, bLive);
1875 if( aPopulator==0 ) rc = SQLITE_NOMEM;
1876 for(i=0; i<pConfig->nCol && rc==SQLITE_OK; i++){
1877 int n; const char *z;
1878 rc = fts5ApiColumnText((Fts5Context*)pCsr, i, &z, &n);
1879 if( rc==SQLITE_OK ){
1880 rc = sqlite3Fts5ExprPopulatePoslists(
1881 pConfig, pCsr->pExpr, aPopulator, i, z, n
1885 sqlite3_free(aPopulator);
1887 if( pCsr->pSorter ){
1888 sqlite3Fts5ExprCheckPoslists(pCsr->pExpr, pCsr->pSorter->iRowid);
1891 CsrFlagClear(pCsr, FTS5CSR_REQUIRE_POSLIST);
1894 if( pCsr->pSorter && pConfig->eDetail==FTS5_DETAIL_FULL ){
1895 Fts5Sorter *pSorter = pCsr->pSorter;
1896 int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
1897 *pn = pSorter->aIdx[iPhrase] - i1;
1898 *pa = &pSorter->aPoslist[i1];
1899 }else{
1900 *pn = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa);
1903 return rc;
1907 ** Ensure that the Fts5Cursor.nInstCount and aInst[] variables are populated
1908 ** correctly for the current view. Return SQLITE_OK if successful, or an
1909 ** SQLite error code otherwise.
1911 static int fts5CacheInstArray(Fts5Cursor *pCsr){
1912 int rc = SQLITE_OK;
1913 Fts5PoslistReader *aIter; /* One iterator for each phrase */
1914 int nIter; /* Number of iterators/phrases */
1915 int nCol = ((Fts5Table*)pCsr->base.pVtab)->pConfig->nCol;
1917 nIter = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
1918 if( pCsr->aInstIter==0 ){
1919 sqlite3_int64 nByte = sizeof(Fts5PoslistReader) * nIter;
1920 pCsr->aInstIter = (Fts5PoslistReader*)sqlite3Fts5MallocZero(&rc, nByte);
1922 aIter = pCsr->aInstIter;
1924 if( aIter ){
1925 int nInst = 0; /* Number instances seen so far */
1926 int i;
1928 /* Initialize all iterators */
1929 for(i=0; i<nIter && rc==SQLITE_OK; i++){
1930 const u8 *a;
1931 int n;
1932 rc = fts5CsrPoslist(pCsr, i, &a, &n);
1933 if( rc==SQLITE_OK ){
1934 sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]);
1938 if( rc==SQLITE_OK ){
1939 while( 1 ){
1940 int *aInst;
1941 int iBest = -1;
1942 for(i=0; i<nIter; i++){
1943 if( (aIter[i].bEof==0)
1944 && (iBest<0 || aIter[i].iPos<aIter[iBest].iPos)
1946 iBest = i;
1949 if( iBest<0 ) break;
1951 nInst++;
1952 if( nInst>=pCsr->nInstAlloc ){
1953 int nNewSize = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
1954 aInst = (int*)sqlite3_realloc64(
1955 pCsr->aInst, nNewSize*sizeof(int)*3
1957 if( aInst ){
1958 pCsr->aInst = aInst;
1959 pCsr->nInstAlloc = nNewSize;
1960 }else{
1961 nInst--;
1962 rc = SQLITE_NOMEM;
1963 break;
1967 aInst = &pCsr->aInst[3 * (nInst-1)];
1968 aInst[0] = iBest;
1969 aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos);
1970 aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos);
1971 if( aInst[1]<0 || aInst[1]>=nCol ){
1972 rc = FTS5_CORRUPT;
1973 break;
1975 sqlite3Fts5PoslistReaderNext(&aIter[iBest]);
1979 pCsr->nInstCount = nInst;
1980 CsrFlagClear(pCsr, FTS5CSR_REQUIRE_INST);
1982 return rc;
1985 static int fts5ApiInstCount(Fts5Context *pCtx, int *pnInst){
1986 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
1987 int rc = SQLITE_OK;
1988 if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0
1989 || SQLITE_OK==(rc = fts5CacheInstArray(pCsr)) ){
1990 *pnInst = pCsr->nInstCount;
1992 return rc;
1995 static int fts5ApiInst(
1996 Fts5Context *pCtx,
1997 int iIdx,
1998 int *piPhrase,
1999 int *piCol,
2000 int *piOff
2002 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
2003 int rc = SQLITE_OK;
2004 if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0
2005 || SQLITE_OK==(rc = fts5CacheInstArray(pCsr))
2007 if( iIdx<0 || iIdx>=pCsr->nInstCount ){
2008 rc = SQLITE_RANGE;
2009 #if 0
2010 }else if( fts5IsOffsetless((Fts5Table*)pCsr->base.pVtab) ){
2011 *piPhrase = pCsr->aInst[iIdx*3];
2012 *piCol = pCsr->aInst[iIdx*3 + 2];
2013 *piOff = -1;
2014 #endif
2015 }else{
2016 *piPhrase = pCsr->aInst[iIdx*3];
2017 *piCol = pCsr->aInst[iIdx*3 + 1];
2018 *piOff = pCsr->aInst[iIdx*3 + 2];
2021 return rc;
2024 static sqlite3_int64 fts5ApiRowid(Fts5Context *pCtx){
2025 return fts5CursorRowid((Fts5Cursor*)pCtx);
2028 static int fts5ColumnSizeCb(
2029 void *pContext, /* Pointer to int */
2030 int tflags,
2031 const char *pUnused, /* Buffer containing token */
2032 int nUnused, /* Size of token in bytes */
2033 int iUnused1, /* Start offset of token */
2034 int iUnused2 /* End offset of token */
2036 int *pCnt = (int*)pContext;
2037 UNUSED_PARAM2(pUnused, nUnused);
2038 UNUSED_PARAM2(iUnused1, iUnused2);
2039 if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){
2040 (*pCnt)++;
2042 return SQLITE_OK;
2045 static int fts5ApiColumnSize(Fts5Context *pCtx, int iCol, int *pnToken){
2046 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
2047 Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
2048 Fts5Config *pConfig = pTab->p.pConfig;
2049 int rc = SQLITE_OK;
2051 if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_DOCSIZE) ){
2052 if( pConfig->bColumnsize ){
2053 i64 iRowid = fts5CursorRowid(pCsr);
2054 rc = sqlite3Fts5StorageDocsize(pTab->pStorage, iRowid, pCsr->aColumnSize);
2055 }else if( pConfig->zContent==0 ){
2056 int i;
2057 for(i=0; i<pConfig->nCol; i++){
2058 if( pConfig->abUnindexed[i]==0 ){
2059 pCsr->aColumnSize[i] = -1;
2062 }else{
2063 int i;
2064 for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
2065 if( pConfig->abUnindexed[i]==0 ){
2066 const char *z; int n;
2067 void *p = (void*)(&pCsr->aColumnSize[i]);
2068 pCsr->aColumnSize[i] = 0;
2069 rc = fts5ApiColumnText(pCtx, i, &z, &n);
2070 if( rc==SQLITE_OK ){
2071 rc = sqlite3Fts5Tokenize(
2072 pConfig, FTS5_TOKENIZE_AUX, z, n, p, fts5ColumnSizeCb
2078 CsrFlagClear(pCsr, FTS5CSR_REQUIRE_DOCSIZE);
2080 if( iCol<0 ){
2081 int i;
2082 *pnToken = 0;
2083 for(i=0; i<pConfig->nCol; i++){
2084 *pnToken += pCsr->aColumnSize[i];
2086 }else if( iCol<pConfig->nCol ){
2087 *pnToken = pCsr->aColumnSize[iCol];
2088 }else{
2089 *pnToken = 0;
2090 rc = SQLITE_RANGE;
2092 return rc;
2096 ** Implementation of the xSetAuxdata() method.
2098 static int fts5ApiSetAuxdata(
2099 Fts5Context *pCtx, /* Fts5 context */
2100 void *pPtr, /* Pointer to save as auxdata */
2101 void(*xDelete)(void*) /* Destructor for pPtr (or NULL) */
2103 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
2104 Fts5Auxdata *pData;
2106 /* Search through the cursors list of Fts5Auxdata objects for one that
2107 ** corresponds to the currently executing auxiliary function. */
2108 for(pData=pCsr->pAuxdata; pData; pData=pData->pNext){
2109 if( pData->pAux==pCsr->pAux ) break;
2112 if( pData ){
2113 if( pData->xDelete ){
2114 pData->xDelete(pData->pPtr);
2116 }else{
2117 int rc = SQLITE_OK;
2118 pData = (Fts5Auxdata*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Auxdata));
2119 if( pData==0 ){
2120 if( xDelete ) xDelete(pPtr);
2121 return rc;
2123 pData->pAux = pCsr->pAux;
2124 pData->pNext = pCsr->pAuxdata;
2125 pCsr->pAuxdata = pData;
2128 pData->xDelete = xDelete;
2129 pData->pPtr = pPtr;
2130 return SQLITE_OK;
2133 static void *fts5ApiGetAuxdata(Fts5Context *pCtx, int bClear){
2134 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
2135 Fts5Auxdata *pData;
2136 void *pRet = 0;
2138 for(pData=pCsr->pAuxdata; pData; pData=pData->pNext){
2139 if( pData->pAux==pCsr->pAux ) break;
2142 if( pData ){
2143 pRet = pData->pPtr;
2144 if( bClear ){
2145 pData->pPtr = 0;
2146 pData->xDelete = 0;
2150 return pRet;
2153 static void fts5ApiPhraseNext(
2154 Fts5Context *pUnused,
2155 Fts5PhraseIter *pIter,
2156 int *piCol, int *piOff
2158 UNUSED_PARAM(pUnused);
2159 if( pIter->a>=pIter->b ){
2160 *piCol = -1;
2161 *piOff = -1;
2162 }else{
2163 int iVal;
2164 pIter->a += fts5GetVarint32(pIter->a, iVal);
2165 if( iVal==1 ){
2166 pIter->a += fts5GetVarint32(pIter->a, iVal);
2167 *piCol = iVal;
2168 *piOff = 0;
2169 pIter->a += fts5GetVarint32(pIter->a, iVal);
2171 *piOff += (iVal-2);
2175 static int fts5ApiPhraseFirst(
2176 Fts5Context *pCtx,
2177 int iPhrase,
2178 Fts5PhraseIter *pIter,
2179 int *piCol, int *piOff
2181 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
2182 int n;
2183 int rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
2184 if( rc==SQLITE_OK ){
2185 assert( pIter->a || n==0 );
2186 pIter->b = (pIter->a ? &pIter->a[n] : 0);
2187 *piCol = 0;
2188 *piOff = 0;
2189 fts5ApiPhraseNext(pCtx, pIter, piCol, piOff);
2191 return rc;
2194 static void fts5ApiPhraseNextColumn(
2195 Fts5Context *pCtx,
2196 Fts5PhraseIter *pIter,
2197 int *piCol
2199 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
2200 Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
2202 if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
2203 if( pIter->a>=pIter->b ){
2204 *piCol = -1;
2205 }else{
2206 int iIncr;
2207 pIter->a += fts5GetVarint32(&pIter->a[0], iIncr);
2208 *piCol += (iIncr-2);
2210 }else{
2211 while( 1 ){
2212 int dummy;
2213 if( pIter->a>=pIter->b ){
2214 *piCol = -1;
2215 return;
2217 if( pIter->a[0]==0x01 ) break;
2218 pIter->a += fts5GetVarint32(pIter->a, dummy);
2220 pIter->a += 1 + fts5GetVarint32(&pIter->a[1], *piCol);
2224 static int fts5ApiPhraseFirstColumn(
2225 Fts5Context *pCtx,
2226 int iPhrase,
2227 Fts5PhraseIter *pIter,
2228 int *piCol
2230 int rc = SQLITE_OK;
2231 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
2232 Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
2234 if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
2235 Fts5Sorter *pSorter = pCsr->pSorter;
2236 int n;
2237 if( pSorter ){
2238 int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
2239 n = pSorter->aIdx[iPhrase] - i1;
2240 pIter->a = &pSorter->aPoslist[i1];
2241 }else{
2242 rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, iPhrase, &pIter->a, &n);
2244 if( rc==SQLITE_OK ){
2245 assert( pIter->a || n==0 );
2246 pIter->b = (pIter->a ? &pIter->a[n] : 0);
2247 *piCol = 0;
2248 fts5ApiPhraseNextColumn(pCtx, pIter, piCol);
2250 }else{
2251 int n;
2252 rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
2253 if( rc==SQLITE_OK ){
2254 assert( pIter->a || n==0 );
2255 pIter->b = (pIter->a ? &pIter->a[n] : 0);
2256 if( n<=0 ){
2257 *piCol = -1;
2258 }else if( pIter->a[0]==0x01 ){
2259 pIter->a += 1 + fts5GetVarint32(&pIter->a[1], *piCol);
2260 }else{
2261 *piCol = 0;
2266 return rc;
2270 static int fts5ApiQueryPhrase(Fts5Context*, int, void*,
2271 int(*)(const Fts5ExtensionApi*, Fts5Context*, void*)
2274 static const Fts5ExtensionApi sFts5Api = {
2275 2, /* iVersion */
2276 fts5ApiUserData,
2277 fts5ApiColumnCount,
2278 fts5ApiRowCount,
2279 fts5ApiColumnTotalSize,
2280 fts5ApiTokenize,
2281 fts5ApiPhraseCount,
2282 fts5ApiPhraseSize,
2283 fts5ApiInstCount,
2284 fts5ApiInst,
2285 fts5ApiRowid,
2286 fts5ApiColumnText,
2287 fts5ApiColumnSize,
2288 fts5ApiQueryPhrase,
2289 fts5ApiSetAuxdata,
2290 fts5ApiGetAuxdata,
2291 fts5ApiPhraseFirst,
2292 fts5ApiPhraseNext,
2293 fts5ApiPhraseFirstColumn,
2294 fts5ApiPhraseNextColumn,
2298 ** Implementation of API function xQueryPhrase().
2300 static int fts5ApiQueryPhrase(
2301 Fts5Context *pCtx,
2302 int iPhrase,
2303 void *pUserData,
2304 int(*xCallback)(const Fts5ExtensionApi*, Fts5Context*, void*)
2306 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
2307 Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
2308 int rc;
2309 Fts5Cursor *pNew = 0;
2311 rc = fts5OpenMethod(pCsr->base.pVtab, (sqlite3_vtab_cursor**)&pNew);
2312 if( rc==SQLITE_OK ){
2313 pNew->ePlan = FTS5_PLAN_MATCH;
2314 pNew->iFirstRowid = SMALLEST_INT64;
2315 pNew->iLastRowid = LARGEST_INT64;
2316 pNew->base.pVtab = (sqlite3_vtab*)pTab;
2317 rc = sqlite3Fts5ExprClonePhrase(pCsr->pExpr, iPhrase, &pNew->pExpr);
2320 if( rc==SQLITE_OK ){
2321 for(rc = fts5CursorFirst(pTab, pNew, 0);
2322 rc==SQLITE_OK && CsrFlagTest(pNew, FTS5CSR_EOF)==0;
2323 rc = fts5NextMethod((sqlite3_vtab_cursor*)pNew)
2325 rc = xCallback(&sFts5Api, (Fts5Context*)pNew, pUserData);
2326 if( rc!=SQLITE_OK ){
2327 if( rc==SQLITE_DONE ) rc = SQLITE_OK;
2328 break;
2333 fts5CloseMethod((sqlite3_vtab_cursor*)pNew);
2334 return rc;
2337 static void fts5ApiInvoke(
2338 Fts5Auxiliary *pAux,
2339 Fts5Cursor *pCsr,
2340 sqlite3_context *context,
2341 int argc,
2342 sqlite3_value **argv
2344 assert( pCsr->pAux==0 );
2345 pCsr->pAux = pAux;
2346 pAux->xFunc(&sFts5Api, (Fts5Context*)pCsr, context, argc, argv);
2347 pCsr->pAux = 0;
2350 static Fts5Cursor *fts5CursorFromCsrid(Fts5Global *pGlobal, i64 iCsrId){
2351 Fts5Cursor *pCsr;
2352 for(pCsr=pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
2353 if( pCsr->iCsrId==iCsrId ) break;
2355 return pCsr;
2358 static void fts5ApiCallback(
2359 sqlite3_context *context,
2360 int argc,
2361 sqlite3_value **argv
2364 Fts5Auxiliary *pAux;
2365 Fts5Cursor *pCsr;
2366 i64 iCsrId;
2368 assert( argc>=1 );
2369 pAux = (Fts5Auxiliary*)sqlite3_user_data(context);
2370 iCsrId = sqlite3_value_int64(argv[0]);
2372 pCsr = fts5CursorFromCsrid(pAux->pGlobal, iCsrId);
2373 if( pCsr==0 || pCsr->ePlan==0 ){
2374 char *zErr = sqlite3_mprintf("no such cursor: %lld", iCsrId);
2375 sqlite3_result_error(context, zErr, -1);
2376 sqlite3_free(zErr);
2377 }else{
2378 fts5ApiInvoke(pAux, pCsr, context, argc-1, &argv[1]);
2384 ** Given cursor id iId, return a pointer to the corresponding Fts5Table
2385 ** object. Or NULL If the cursor id does not exist.
2387 Fts5Table *sqlite3Fts5TableFromCsrid(
2388 Fts5Global *pGlobal, /* FTS5 global context for db handle */
2389 i64 iCsrId /* Id of cursor to find */
2391 Fts5Cursor *pCsr;
2392 pCsr = fts5CursorFromCsrid(pGlobal, iCsrId);
2393 if( pCsr ){
2394 return (Fts5Table*)pCsr->base.pVtab;
2396 return 0;
2400 ** Return a "position-list blob" corresponding to the current position of
2401 ** cursor pCsr via sqlite3_result_blob(). A position-list blob contains
2402 ** the current position-list for each phrase in the query associated with
2403 ** cursor pCsr.
2405 ** A position-list blob begins with (nPhrase-1) varints, where nPhrase is
2406 ** the number of phrases in the query. Following the varints are the
2407 ** concatenated position lists for each phrase, in order.
2409 ** The first varint (if it exists) contains the size of the position list
2410 ** for phrase 0. The second (same disclaimer) contains the size of position
2411 ** list 1. And so on. There is no size field for the final position list,
2412 ** as it can be derived from the total size of the blob.
2414 static int fts5PoslistBlob(sqlite3_context *pCtx, Fts5Cursor *pCsr){
2415 int i;
2416 int rc = SQLITE_OK;
2417 int nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
2418 Fts5Buffer val;
2420 memset(&val, 0, sizeof(Fts5Buffer));
2421 switch( ((Fts5Table*)(pCsr->base.pVtab))->pConfig->eDetail ){
2422 case FTS5_DETAIL_FULL:
2424 /* Append the varints */
2425 for(i=0; i<(nPhrase-1); i++){
2426 const u8 *dummy;
2427 int nByte = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &dummy);
2428 sqlite3Fts5BufferAppendVarint(&rc, &val, nByte);
2431 /* Append the position lists */
2432 for(i=0; i<nPhrase; i++){
2433 const u8 *pPoslist;
2434 int nPoslist;
2435 nPoslist = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &pPoslist);
2436 sqlite3Fts5BufferAppendBlob(&rc, &val, nPoslist, pPoslist);
2438 break;
2440 case FTS5_DETAIL_COLUMNS:
2442 /* Append the varints */
2443 for(i=0; rc==SQLITE_OK && i<(nPhrase-1); i++){
2444 const u8 *dummy;
2445 int nByte;
2446 rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, i, &dummy, &nByte);
2447 sqlite3Fts5BufferAppendVarint(&rc, &val, nByte);
2450 /* Append the position lists */
2451 for(i=0; rc==SQLITE_OK && i<nPhrase; i++){
2452 const u8 *pPoslist;
2453 int nPoslist;
2454 rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, i, &pPoslist, &nPoslist);
2455 sqlite3Fts5BufferAppendBlob(&rc, &val, nPoslist, pPoslist);
2457 break;
2459 default:
2460 break;
2463 sqlite3_result_blob(pCtx, val.p, val.n, sqlite3_free);
2464 return rc;
2468 ** This is the xColumn method, called by SQLite to request a value from
2469 ** the row that the supplied cursor currently points to.
2471 static int fts5ColumnMethod(
2472 sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
2473 sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
2474 int iCol /* Index of column to read value from */
2476 Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab);
2477 Fts5Config *pConfig = pTab->p.pConfig;
2478 Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
2479 int rc = SQLITE_OK;
2481 assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 );
2483 if( pCsr->ePlan==FTS5_PLAN_SPECIAL ){
2484 if( iCol==pConfig->nCol ){
2485 sqlite3_result_int64(pCtx, pCsr->iSpecial);
2487 }else
2489 if( iCol==pConfig->nCol ){
2490 /* User is requesting the value of the special column with the same name
2491 ** as the table. Return the cursor integer id number. This value is only
2492 ** useful in that it may be passed as the first argument to an FTS5
2493 ** auxiliary function. */
2494 sqlite3_result_int64(pCtx, pCsr->iCsrId);
2495 }else if( iCol==pConfig->nCol+1 ){
2497 /* The value of the "rank" column. */
2498 if( pCsr->ePlan==FTS5_PLAN_SOURCE ){
2499 fts5PoslistBlob(pCtx, pCsr);
2500 }else if(
2501 pCsr->ePlan==FTS5_PLAN_MATCH
2502 || pCsr->ePlan==FTS5_PLAN_SORTED_MATCH
2504 if( pCsr->pRank || SQLITE_OK==(rc = fts5FindRankFunction(pCsr)) ){
2505 fts5ApiInvoke(pCsr->pRank, pCsr, pCtx, pCsr->nRankArg, pCsr->apRankArg);
2508 }else if( !fts5IsContentless(pTab) ){
2509 pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
2510 rc = fts5SeekCursor(pCsr, 1);
2511 if( rc==SQLITE_OK ){
2512 sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
2514 pConfig->pzErrmsg = 0;
2516 return rc;
2521 ** This routine implements the xFindFunction method for the FTS3
2522 ** virtual table.
2524 static int fts5FindFunctionMethod(
2525 sqlite3_vtab *pVtab, /* Virtual table handle */
2526 int nUnused, /* Number of SQL function arguments */
2527 const char *zName, /* Name of SQL function */
2528 void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
2529 void **ppArg /* OUT: User data for *pxFunc */
2531 Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
2532 Fts5Auxiliary *pAux;
2534 UNUSED_PARAM(nUnused);
2535 pAux = fts5FindAuxiliary(pTab, zName);
2536 if( pAux ){
2537 *pxFunc = fts5ApiCallback;
2538 *ppArg = (void*)pAux;
2539 return 1;
2542 /* No function of the specified name was found. Return 0. */
2543 return 0;
2547 ** Implementation of FTS5 xRename method. Rename an fts5 table.
2549 static int fts5RenameMethod(
2550 sqlite3_vtab *pVtab, /* Virtual table handle */
2551 const char *zName /* New name of table */
2553 Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
2554 return sqlite3Fts5StorageRename(pTab->pStorage, zName);
2557 int sqlite3Fts5FlushToDisk(Fts5Table *pTab){
2558 fts5TripCursors((Fts5FullTable*)pTab);
2559 return sqlite3Fts5StorageSync(((Fts5FullTable*)pTab)->pStorage);
2563 ** The xSavepoint() method.
2565 ** Flush the contents of the pending-terms table to disk.
2567 static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
2568 UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
2569 fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_SAVEPOINT, iSavepoint);
2570 return sqlite3Fts5FlushToDisk((Fts5Table*)pVtab);
2574 ** The xRelease() method.
2576 ** This is a no-op.
2578 static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
2579 UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
2580 fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_RELEASE, iSavepoint);
2581 return sqlite3Fts5FlushToDisk((Fts5Table*)pVtab);
2585 ** The xRollbackTo() method.
2587 ** Discard the contents of the pending terms table.
2589 static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
2590 Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
2591 UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
2592 fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint);
2593 fts5TripCursors(pTab);
2594 return sqlite3Fts5StorageRollback(pTab->pStorage);
2598 ** Register a new auxiliary function with global context pGlobal.
2600 static int fts5CreateAux(
2601 fts5_api *pApi, /* Global context (one per db handle) */
2602 const char *zName, /* Name of new function */
2603 void *pUserData, /* User data for aux. function */
2604 fts5_extension_function xFunc, /* Aux. function implementation */
2605 void(*xDestroy)(void*) /* Destructor for pUserData */
2607 Fts5Global *pGlobal = (Fts5Global*)pApi;
2608 int rc = sqlite3_overload_function(pGlobal->db, zName, -1);
2609 if( rc==SQLITE_OK ){
2610 Fts5Auxiliary *pAux;
2611 sqlite3_int64 nName; /* Size of zName in bytes, including \0 */
2612 sqlite3_int64 nByte; /* Bytes of space to allocate */
2614 nName = strlen(zName) + 1;
2615 nByte = sizeof(Fts5Auxiliary) + nName;
2616 pAux = (Fts5Auxiliary*)sqlite3_malloc64(nByte);
2617 if( pAux ){
2618 memset(pAux, 0, (size_t)nByte);
2619 pAux->zFunc = (char*)&pAux[1];
2620 memcpy(pAux->zFunc, zName, nName);
2621 pAux->pGlobal = pGlobal;
2622 pAux->pUserData = pUserData;
2623 pAux->xFunc = xFunc;
2624 pAux->xDestroy = xDestroy;
2625 pAux->pNext = pGlobal->pAux;
2626 pGlobal->pAux = pAux;
2627 }else{
2628 rc = SQLITE_NOMEM;
2632 return rc;
2636 ** Register a new tokenizer. This is the implementation of the
2637 ** fts5_api.xCreateTokenizer() method.
2639 static int fts5CreateTokenizer(
2640 fts5_api *pApi, /* Global context (one per db handle) */
2641 const char *zName, /* Name of new function */
2642 void *pUserData, /* User data for aux. function */
2643 fts5_tokenizer *pTokenizer, /* Tokenizer implementation */
2644 void(*xDestroy)(void*) /* Destructor for pUserData */
2646 Fts5Global *pGlobal = (Fts5Global*)pApi;
2647 Fts5TokenizerModule *pNew;
2648 sqlite3_int64 nName; /* Size of zName and its \0 terminator */
2649 sqlite3_int64 nByte; /* Bytes of space to allocate */
2650 int rc = SQLITE_OK;
2652 nName = strlen(zName) + 1;
2653 nByte = sizeof(Fts5TokenizerModule) + nName;
2654 pNew = (Fts5TokenizerModule*)sqlite3_malloc64(nByte);
2655 if( pNew ){
2656 memset(pNew, 0, (size_t)nByte);
2657 pNew->zName = (char*)&pNew[1];
2658 memcpy(pNew->zName, zName, nName);
2659 pNew->pUserData = pUserData;
2660 pNew->x = *pTokenizer;
2661 pNew->xDestroy = xDestroy;
2662 pNew->pNext = pGlobal->pTok;
2663 pGlobal->pTok = pNew;
2664 if( pNew->pNext==0 ){
2665 pGlobal->pDfltTok = pNew;
2667 }else{
2668 rc = SQLITE_NOMEM;
2671 return rc;
2674 static Fts5TokenizerModule *fts5LocateTokenizer(
2675 Fts5Global *pGlobal,
2676 const char *zName
2678 Fts5TokenizerModule *pMod = 0;
2680 if( zName==0 ){
2681 pMod = pGlobal->pDfltTok;
2682 }else{
2683 for(pMod=pGlobal->pTok; pMod; pMod=pMod->pNext){
2684 if( sqlite3_stricmp(zName, pMod->zName)==0 ) break;
2688 return pMod;
2692 ** Find a tokenizer. This is the implementation of the
2693 ** fts5_api.xFindTokenizer() method.
2695 static int fts5FindTokenizer(
2696 fts5_api *pApi, /* Global context (one per db handle) */
2697 const char *zName, /* Name of new function */
2698 void **ppUserData,
2699 fts5_tokenizer *pTokenizer /* Populate this object */
2701 int rc = SQLITE_OK;
2702 Fts5TokenizerModule *pMod;
2704 pMod = fts5LocateTokenizer((Fts5Global*)pApi, zName);
2705 if( pMod ){
2706 *pTokenizer = pMod->x;
2707 *ppUserData = pMod->pUserData;
2708 }else{
2709 memset(pTokenizer, 0, sizeof(fts5_tokenizer));
2710 rc = SQLITE_ERROR;
2713 return rc;
2716 int sqlite3Fts5GetTokenizer(
2717 Fts5Global *pGlobal,
2718 const char **azArg,
2719 int nArg,
2720 Fts5Config *pConfig,
2721 char **pzErr
2723 Fts5TokenizerModule *pMod;
2724 int rc = SQLITE_OK;
2726 pMod = fts5LocateTokenizer(pGlobal, nArg==0 ? 0 : azArg[0]);
2727 if( pMod==0 ){
2728 assert( nArg>0 );
2729 rc = SQLITE_ERROR;
2730 *pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
2731 }else{
2732 rc = pMod->x.xCreate(
2733 pMod->pUserData, (azArg?&azArg[1]:0), (nArg?nArg-1:0), &pConfig->pTok
2735 pConfig->pTokApi = &pMod->x;
2736 if( rc!=SQLITE_OK ){
2737 if( pzErr ) *pzErr = sqlite3_mprintf("error in tokenizer constructor");
2738 }else{
2739 pConfig->ePattern = sqlite3Fts5TokenizerPattern(
2740 pMod->x.xCreate, pConfig->pTok
2745 if( rc!=SQLITE_OK ){
2746 pConfig->pTokApi = 0;
2747 pConfig->pTok = 0;
2750 return rc;
2753 static void fts5ModuleDestroy(void *pCtx){
2754 Fts5TokenizerModule *pTok, *pNextTok;
2755 Fts5Auxiliary *pAux, *pNextAux;
2756 Fts5Global *pGlobal = (Fts5Global*)pCtx;
2758 for(pAux=pGlobal->pAux; pAux; pAux=pNextAux){
2759 pNextAux = pAux->pNext;
2760 if( pAux->xDestroy ) pAux->xDestroy(pAux->pUserData);
2761 sqlite3_free(pAux);
2764 for(pTok=pGlobal->pTok; pTok; pTok=pNextTok){
2765 pNextTok = pTok->pNext;
2766 if( pTok->xDestroy ) pTok->xDestroy(pTok->pUserData);
2767 sqlite3_free(pTok);
2770 sqlite3_free(pGlobal);
2773 static void fts5Fts5Func(
2774 sqlite3_context *pCtx, /* Function call context */
2775 int nArg, /* Number of args */
2776 sqlite3_value **apArg /* Function arguments */
2778 Fts5Global *pGlobal = (Fts5Global*)sqlite3_user_data(pCtx);
2779 fts5_api **ppApi;
2780 UNUSED_PARAM(nArg);
2781 assert( nArg==1 );
2782 ppApi = (fts5_api**)sqlite3_value_pointer(apArg[0], "fts5_api_ptr");
2783 if( ppApi ) *ppApi = &pGlobal->api;
2787 ** Implementation of fts5_source_id() function.
2789 static void fts5SourceIdFunc(
2790 sqlite3_context *pCtx, /* Function call context */
2791 int nArg, /* Number of args */
2792 sqlite3_value **apUnused /* Function arguments */
2794 assert( nArg==0 );
2795 UNUSED_PARAM2(nArg, apUnused);
2796 sqlite3_result_text(pCtx, "--FTS5-SOURCE-ID--", -1, SQLITE_TRANSIENT);
2800 ** Return true if zName is the extension on one of the shadow tables used
2801 ** by this module.
2803 static int fts5ShadowName(const char *zName){
2804 static const char *azName[] = {
2805 "config", "content", "data", "docsize", "idx"
2807 unsigned int i;
2808 for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){
2809 if( sqlite3_stricmp(zName, azName[i])==0 ) return 1;
2811 return 0;
2814 static int fts5Init(sqlite3 *db){
2815 static const sqlite3_module fts5Mod = {
2816 /* iVersion */ 3,
2817 /* xCreate */ fts5CreateMethod,
2818 /* xConnect */ fts5ConnectMethod,
2819 /* xBestIndex */ fts5BestIndexMethod,
2820 /* xDisconnect */ fts5DisconnectMethod,
2821 /* xDestroy */ fts5DestroyMethod,
2822 /* xOpen */ fts5OpenMethod,
2823 /* xClose */ fts5CloseMethod,
2824 /* xFilter */ fts5FilterMethod,
2825 /* xNext */ fts5NextMethod,
2826 /* xEof */ fts5EofMethod,
2827 /* xColumn */ fts5ColumnMethod,
2828 /* xRowid */ fts5RowidMethod,
2829 /* xUpdate */ fts5UpdateMethod,
2830 /* xBegin */ fts5BeginMethod,
2831 /* xSync */ fts5SyncMethod,
2832 /* xCommit */ fts5CommitMethod,
2833 /* xRollback */ fts5RollbackMethod,
2834 /* xFindFunction */ fts5FindFunctionMethod,
2835 /* xRename */ fts5RenameMethod,
2836 /* xSavepoint */ fts5SavepointMethod,
2837 /* xRelease */ fts5ReleaseMethod,
2838 /* xRollbackTo */ fts5RollbackToMethod,
2839 /* xShadowName */ fts5ShadowName
2842 int rc;
2843 Fts5Global *pGlobal = 0;
2845 pGlobal = (Fts5Global*)sqlite3_malloc(sizeof(Fts5Global));
2846 if( pGlobal==0 ){
2847 rc = SQLITE_NOMEM;
2848 }else{
2849 void *p = (void*)pGlobal;
2850 memset(pGlobal, 0, sizeof(Fts5Global));
2851 pGlobal->db = db;
2852 pGlobal->api.iVersion = 2;
2853 pGlobal->api.xCreateFunction = fts5CreateAux;
2854 pGlobal->api.xCreateTokenizer = fts5CreateTokenizer;
2855 pGlobal->api.xFindTokenizer = fts5FindTokenizer;
2856 rc = sqlite3_create_module_v2(db, "fts5", &fts5Mod, p, fts5ModuleDestroy);
2857 if( rc==SQLITE_OK ) rc = sqlite3Fts5IndexInit(db);
2858 if( rc==SQLITE_OK ) rc = sqlite3Fts5ExprInit(pGlobal, db);
2859 if( rc==SQLITE_OK ) rc = sqlite3Fts5AuxInit(&pGlobal->api);
2860 if( rc==SQLITE_OK ) rc = sqlite3Fts5TokenizerInit(&pGlobal->api);
2861 if( rc==SQLITE_OK ) rc = sqlite3Fts5VocabInit(pGlobal, db);
2862 if( rc==SQLITE_OK ){
2863 rc = sqlite3_create_function(
2864 db, "fts5", 1, SQLITE_UTF8, p, fts5Fts5Func, 0, 0
2867 if( rc==SQLITE_OK ){
2868 rc = sqlite3_create_function(
2869 db, "fts5_source_id", 0, SQLITE_UTF8, p, fts5SourceIdFunc, 0, 0
2874 /* If SQLITE_FTS5_ENABLE_TEST_MI is defined, assume that the file
2875 ** fts5_test_mi.c is compiled and linked into the executable. And call
2876 ** its entry point to enable the matchinfo() demo. */
2877 #ifdef SQLITE_FTS5_ENABLE_TEST_MI
2878 if( rc==SQLITE_OK ){
2879 extern int sqlite3Fts5TestRegisterMatchinfo(sqlite3*);
2880 rc = sqlite3Fts5TestRegisterMatchinfo(db);
2882 #endif
2884 return rc;
2888 ** The following functions are used to register the module with SQLite. If
2889 ** this module is being built as part of the SQLite core (SQLITE_CORE is
2890 ** defined), then sqlite3_open() will call sqlite3Fts5Init() directly.
2892 ** Or, if this module is being built as a loadable extension,
2893 ** sqlite3Fts5Init() is omitted and the two standard entry points
2894 ** sqlite3_fts_init() and sqlite3_fts5_init() defined instead.
2896 #ifndef SQLITE_CORE
2897 #ifdef _WIN32
2898 __declspec(dllexport)
2899 #endif
2900 int sqlite3_fts_init(
2901 sqlite3 *db,
2902 char **pzErrMsg,
2903 const sqlite3_api_routines *pApi
2905 SQLITE_EXTENSION_INIT2(pApi);
2906 (void)pzErrMsg; /* Unused parameter */
2907 return fts5Init(db);
2910 #ifdef _WIN32
2911 __declspec(dllexport)
2912 #endif
2913 int sqlite3_fts5_init(
2914 sqlite3 *db,
2915 char **pzErrMsg,
2916 const sqlite3_api_routines *pApi
2918 SQLITE_EXTENSION_INIT2(pApi);
2919 (void)pzErrMsg; /* Unused parameter */
2920 return fts5Init(db);
2922 #else
2923 int sqlite3Fts5Init(sqlite3 *db){
2924 return fts5Init(db);
2926 #endif