modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/fts5/fts5_main.c (about)

     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.
    10  **
    11  ******************************************************************************
    12  **
    13  ** This is an SQLite module implementing full-text search.
    14  */
    15  
    16  
    17  #include "fts5Int.h"
    18  
    19  /*
    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.
    24  */
    25  int sqlite3_fts5_may_be_corrupt = 1;
    26  
    27  
    28  typedef struct Fts5Auxdata Fts5Auxdata;
    29  typedef struct Fts5Auxiliary Fts5Auxiliary;
    30  typedef struct Fts5Cursor Fts5Cursor;
    31  typedef struct Fts5Sorter Fts5Sorter;
    32  typedef struct Fts5Table Fts5Table;
    33  typedef struct Fts5TokenizerModule Fts5TokenizerModule;
    34  
    35  /*
    36  ** NOTES ON TRANSACTIONS: 
    37  **
    38  ** SQLite invokes the following virtual table methods as transactions are 
    39  ** opened and closed by the user:
    40  **
    41  **     xBegin():    Start of a new transaction.
    42  **     xSync():     Initial part of two-phase commit.
    43  **     xCommit():   Final part of two-phase commit.
    44  **     xRollback(): Rollback the transaction.
    45  **
    46  ** Anything that is required as part of a commit that may fail is performed
    47  ** in the xSync() callback. Current versions of SQLite ignore any errors 
    48  ** returned by xCommit().
    49  **
    50  ** And as sub-transactions are opened/closed:
    51  **
    52  **     xSavepoint(int S):  Open savepoint S.
    53  **     xRelease(int S):    Commit and close savepoint S.
    54  **     xRollbackTo(int S): Rollback to start of savepoint S.
    55  **
    56  ** During a write-transaction the fts5_index.c module may cache some data 
    57  ** in-memory. It is flushed to disk whenever xSync(), xRelease() or
    58  ** xSavepoint() is called. And discarded whenever xRollback() or xRollbackTo() 
    59  ** is called.
    60  **
    61  ** Additionally, if SQLITE_DEBUG is defined, an instance of the following
    62  ** structure is used to record the current transaction state. This information
    63  ** is not required, but it is used in the assert() statements executed by
    64  ** function fts5CheckTransactionState() (see below).
    65  */
    66  struct Fts5TransactionState {
    67    int eState;                     /* 0==closed, 1==open, 2==synced */
    68    int iSavepoint;                 /* Number of open savepoints (0 -> none) */
    69  };
    70  
    71  /*
    72  ** A single object of this type is allocated when the FTS5 module is 
    73  ** registered with a database handle. It is used to store pointers to
    74  ** all registered FTS5 extensions - tokenizers and auxiliary functions.
    75  */
    76  struct Fts5Global {
    77    fts5_api api;                   /* User visible part of object (see fts5.h) */
    78    sqlite3 *db;                    /* Associated database connection */ 
    79    i64 iNextId;                    /* Used to allocate unique cursor ids */
    80    Fts5Auxiliary *pAux;            /* First in list of all aux. functions */
    81    Fts5TokenizerModule *pTok;      /* First in list of all tokenizer modules */
    82    Fts5TokenizerModule *pDfltTok;  /* Default tokenizer module */
    83    Fts5Cursor *pCsr;               /* First in list of all open cursors */
    84  };
    85  
    86  /*
    87  ** Each auxiliary function registered with the FTS5 module is represented
    88  ** by an object of the following type. All such objects are stored as part
    89  ** of the Fts5Global.pAux list.
    90  */
    91  struct Fts5Auxiliary {
    92    Fts5Global *pGlobal;            /* Global context for this function */
    93    char *zFunc;                    /* Function name (nul-terminated) */
    94    void *pUserData;                /* User-data pointer */
    95    fts5_extension_function xFunc;  /* Callback function */
    96    void (*xDestroy)(void*);        /* Destructor function */
    97    Fts5Auxiliary *pNext;           /* Next registered auxiliary function */
    98  };
    99  
   100  /*
   101  ** Each tokenizer module registered with the FTS5 module is represented
   102  ** by an object of the following type. All such objects are stored as part
   103  ** of the Fts5Global.pTok list.
   104  */
   105  struct Fts5TokenizerModule {
   106    char *zName;                    /* Name of tokenizer */
   107    void *pUserData;                /* User pointer passed to xCreate() */
   108    fts5_tokenizer x;               /* Tokenizer functions */
   109    void (*xDestroy)(void*);        /* Destructor function */
   110    Fts5TokenizerModule *pNext;     /* Next registered tokenizer module */
   111  };
   112  
   113  /*
   114  ** Virtual-table object.
   115  */
   116  struct Fts5Table {
   117    sqlite3_vtab base;              /* Base class used by SQLite core */
   118    Fts5Config *pConfig;            /* Virtual table configuration */
   119    Fts5Index *pIndex;              /* Full-text index */
   120    Fts5Storage *pStorage;          /* Document store */
   121    Fts5Global *pGlobal;            /* Global (connection wide) data */
   122    Fts5Cursor *pSortCsr;           /* Sort data from this cursor */
   123  #ifdef SQLITE_DEBUG
   124    struct Fts5TransactionState ts;
   125  #endif
   126  };
   127  
   128  struct Fts5MatchPhrase {
   129    Fts5Buffer *pPoslist;           /* Pointer to current poslist */
   130    int nTerm;                      /* Size of phrase in terms */
   131  };
   132  
   133  /*
   134  ** pStmt:
   135  **   SELECT rowid, <fts> FROM <fts> ORDER BY +rank;
   136  **
   137  ** aIdx[]:
   138  **   There is one entry in the aIdx[] array for each phrase in the query,
   139  **   the value of which is the offset within aPoslist[] following the last 
   140  **   byte of the position list for the corresponding phrase.
   141  */
   142  struct Fts5Sorter {
   143    sqlite3_stmt *pStmt;
   144    i64 iRowid;                     /* Current rowid */
   145    const u8 *aPoslist;             /* Position lists for current row */
   146    int nIdx;                       /* Number of entries in aIdx[] */
   147    int aIdx[1];                    /* Offsets into aPoslist for current row */
   148  };
   149  
   150  
   151  /*
   152  ** Virtual-table cursor object.
   153  **
   154  ** iSpecial:
   155  **   If this is a 'special' query (refer to function fts5SpecialMatch()), 
   156  **   then this variable contains the result of the query. 
   157  **
   158  ** iFirstRowid, iLastRowid:
   159  **   These variables are only used for FTS5_PLAN_MATCH cursors. Assuming the
   160  **   cursor iterates in ascending order of rowids, iFirstRowid is the lower
   161  **   limit of rowids to return, and iLastRowid the upper. In other words, the
   162  **   WHERE clause in the user's query might have been:
   163  **
   164  **       <tbl> MATCH <expr> AND rowid BETWEEN $iFirstRowid AND $iLastRowid
   165  **
   166  **   If the cursor iterates in descending order of rowid, iFirstRowid
   167  **   is the upper limit (i.e. the "first" rowid visited) and iLastRowid
   168  **   the lower.
   169  */
   170  struct Fts5Cursor {
   171    sqlite3_vtab_cursor base;       /* Base class used by SQLite core */
   172    Fts5Cursor *pNext;              /* Next cursor in Fts5Cursor.pCsr list */
   173    int *aColumnSize;               /* Values for xColumnSize() */
   174    i64 iCsrId;                     /* Cursor id */
   175  
   176    /* Zero from this point onwards on cursor reset */
   177    int ePlan;                      /* FTS5_PLAN_XXX value */
   178    int bDesc;                      /* True for "ORDER BY rowid DESC" queries */
   179    i64 iFirstRowid;                /* Return no rowids earlier than this */
   180    i64 iLastRowid;                 /* Return no rowids later than this */
   181    sqlite3_stmt *pStmt;            /* Statement used to read %_content */
   182    Fts5Expr *pExpr;                /* Expression for MATCH queries */
   183    Fts5Sorter *pSorter;            /* Sorter for "ORDER BY rank" queries */
   184    int csrflags;                   /* Mask of cursor flags (see below) */
   185    i64 iSpecial;                   /* Result of special query */
   186  
   187    /* "rank" function. Populated on demand from vtab.xColumn(). */
   188    char *zRank;                    /* Custom rank function */
   189    char *zRankArgs;                /* Custom rank function args */
   190    Fts5Auxiliary *pRank;           /* Rank callback (or NULL) */
   191    int nRankArg;                   /* Number of trailing arguments for rank() */
   192    sqlite3_value **apRankArg;      /* Array of trailing arguments */
   193    sqlite3_stmt *pRankArgStmt;     /* Origin of objects in apRankArg[] */
   194  
   195    /* Auxiliary data storage */
   196    Fts5Auxiliary *pAux;            /* Currently executing extension function */
   197    Fts5Auxdata *pAuxdata;          /* First in linked list of saved aux-data */
   198  
   199    /* Cache used by auxiliary functions xInst() and xInstCount() */
   200    Fts5PoslistReader *aInstIter;   /* One for each phrase */
   201    int nInstAlloc;                 /* Size of aInst[] array (entries / 3) */
   202    int nInstCount;                 /* Number of phrase instances */
   203    int *aInst;                     /* 3 integers per phrase instance */
   204  };
   205  
   206  /*
   207  ** Bits that make up the "idxNum" parameter passed indirectly by 
   208  ** xBestIndex() to xFilter().
   209  */
   210  #define FTS5_BI_MATCH        0x0001         /* <tbl> MATCH ? */
   211  #define FTS5_BI_RANK         0x0002         /* rank MATCH ? */
   212  #define FTS5_BI_ROWID_EQ     0x0004         /* rowid == ? */
   213  #define FTS5_BI_ROWID_LE     0x0008         /* rowid <= ? */
   214  #define FTS5_BI_ROWID_GE     0x0010         /* rowid >= ? */
   215  
   216  #define FTS5_BI_ORDER_RANK   0x0020
   217  #define FTS5_BI_ORDER_ROWID  0x0040
   218  #define FTS5_BI_ORDER_DESC   0x0080
   219  
   220  /*
   221  ** Values for Fts5Cursor.csrflags
   222  */
   223  #define FTS5CSR_EOF               0x01
   224  #define FTS5CSR_REQUIRE_CONTENT   0x02
   225  #define FTS5CSR_REQUIRE_DOCSIZE   0x04
   226  #define FTS5CSR_REQUIRE_INST      0x08
   227  #define FTS5CSR_FREE_ZRANK        0x10
   228  #define FTS5CSR_REQUIRE_RESEEK    0x20
   229  #define FTS5CSR_REQUIRE_POSLIST   0x40
   230  
   231  #define BitFlagAllTest(x,y) (((x) & (y))==(y))
   232  #define BitFlagTest(x,y)    (((x) & (y))!=0)
   233  
   234  
   235  /*
   236  ** Macros to Set(), Clear() and Test() cursor flags.
   237  */
   238  #define CsrFlagSet(pCsr, flag)   ((pCsr)->csrflags |= (flag))
   239  #define CsrFlagClear(pCsr, flag) ((pCsr)->csrflags &= ~(flag))
   240  #define CsrFlagTest(pCsr, flag)  ((pCsr)->csrflags & (flag))
   241  
   242  struct Fts5Auxdata {
   243    Fts5Auxiliary *pAux;            /* Extension to which this belongs */
   244    void *pPtr;                     /* Pointer value */
   245    void(*xDelete)(void*);          /* Destructor */
   246    Fts5Auxdata *pNext;             /* Next object in linked list */
   247  };
   248  
   249  #ifdef SQLITE_DEBUG
   250  #define FTS5_BEGIN      1
   251  #define FTS5_SYNC       2
   252  #define FTS5_COMMIT     3
   253  #define FTS5_ROLLBACK   4
   254  #define FTS5_SAVEPOINT  5
   255  #define FTS5_RELEASE    6
   256  #define FTS5_ROLLBACKTO 7
   257  static void fts5CheckTransactionState(Fts5Table *p, int op, int iSavepoint){
   258    switch( op ){
   259      case FTS5_BEGIN:
   260        assert( p->ts.eState==0 );
   261        p->ts.eState = 1;
   262        p->ts.iSavepoint = -1;
   263        break;
   264  
   265      case FTS5_SYNC:
   266        assert( p->ts.eState==1 );
   267        p->ts.eState = 2;
   268        break;
   269  
   270      case FTS5_COMMIT:
   271        assert( p->ts.eState==2 );
   272        p->ts.eState = 0;
   273        break;
   274  
   275      case FTS5_ROLLBACK:
   276        assert( p->ts.eState==1 || p->ts.eState==2 || p->ts.eState==0 );
   277        p->ts.eState = 0;
   278        break;
   279  
   280      case FTS5_SAVEPOINT:
   281        assert( p->ts.eState==1 );
   282        assert( iSavepoint>=0 );
   283        assert( iSavepoint>p->ts.iSavepoint );
   284        p->ts.iSavepoint = iSavepoint;
   285        break;
   286        
   287      case FTS5_RELEASE:
   288        assert( p->ts.eState==1 );
   289        assert( iSavepoint>=0 );
   290        assert( iSavepoint<=p->ts.iSavepoint );
   291        p->ts.iSavepoint = iSavepoint-1;
   292        break;
   293  
   294      case FTS5_ROLLBACKTO:
   295        assert( p->ts.eState==1 );
   296        assert( iSavepoint>=0 );
   297        assert( iSavepoint<=p->ts.iSavepoint );
   298        p->ts.iSavepoint = iSavepoint;
   299        break;
   300    }
   301  }
   302  #else
   303  # define fts5CheckTransactionState(x,y,z)
   304  #endif
   305  
   306  /*
   307  ** Return true if pTab is a contentless table.
   308  */
   309  static int fts5IsContentless(Fts5Table *pTab){
   310    return pTab->pConfig->eContent==FTS5_CONTENT_NONE;
   311  }
   312  
   313  /*
   314  ** Delete a virtual table handle allocated by fts5InitVtab(). 
   315  */
   316  static void fts5FreeVtab(Fts5Table *pTab){
   317    if( pTab ){
   318      sqlite3Fts5IndexClose(pTab->pIndex);
   319      sqlite3Fts5StorageClose(pTab->pStorage);
   320      sqlite3Fts5ConfigFree(pTab->pConfig);
   321      sqlite3_free(pTab);
   322    }
   323  }
   324  
   325  /*
   326  ** The xDisconnect() virtual table method.
   327  */
   328  static int fts5DisconnectMethod(sqlite3_vtab *pVtab){
   329    fts5FreeVtab((Fts5Table*)pVtab);
   330    return SQLITE_OK;
   331  }
   332  
   333  /*
   334  ** The xDestroy() virtual table method.
   335  */
   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((Fts5Table*)pVtab);
   341    }
   342    return rc;
   343  }
   344  
   345  /*
   346  ** This function is the implementation of both the xConnect and xCreate
   347  ** methods of the FTS3 virtual table.
   348  **
   349  ** The argv[] array contains the following:
   350  **
   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.
   355  */
   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 */
   364  ){
   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    Fts5Table *pTab = 0;            /* New virtual table object */
   370  
   371    /* Allocate the new vtab object and parse the configuration */
   372    pTab = (Fts5Table*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Table));
   373    if( rc==SQLITE_OK ){
   374      rc = sqlite3Fts5ConfigParse(pGlobal, db, argc, azConfig, &pConfig, pzErr);
   375      assert( (rc==SQLITE_OK && *pzErr==0) || pConfig==0 );
   376    }
   377    if( rc==SQLITE_OK ){
   378      pTab->pConfig = pConfig;
   379      pTab->pGlobal = pGlobal;
   380    }
   381  
   382    /* Open the index sub-system */
   383    if( rc==SQLITE_OK ){
   384      rc = sqlite3Fts5IndexOpen(pConfig, bCreate, &pTab->pIndex, pzErr);
   385    }
   386  
   387    /* Open the storage sub-system */
   388    if( rc==SQLITE_OK ){
   389      rc = sqlite3Fts5StorageOpen(
   390          pConfig, pTab->pIndex, bCreate, &pTab->pStorage, pzErr
   391      );
   392    }
   393  
   394    /* Call sqlite3_declare_vtab() */
   395    if( rc==SQLITE_OK ){
   396      rc = sqlite3Fts5ConfigDeclareVtab(pConfig);
   397    }
   398  
   399    /* Load the initial configuration */
   400    if( rc==SQLITE_OK ){
   401      assert( pConfig->pzErrmsg==0 );
   402      pConfig->pzErrmsg = pzErr;
   403      rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex);
   404      sqlite3Fts5IndexRollback(pTab->pIndex);
   405      pConfig->pzErrmsg = 0;
   406    }
   407  
   408    if( rc!=SQLITE_OK ){
   409      fts5FreeVtab(pTab);
   410      pTab = 0;
   411    }else if( bCreate ){
   412      fts5CheckTransactionState(pTab, FTS5_BEGIN, 0);
   413    }
   414    *ppVTab = (sqlite3_vtab*)pTab;
   415    return rc;
   416  }
   417  
   418  /*
   419  ** The xConnect() and xCreate() methods for the virtual table. All the
   420  ** work is done in function fts5InitVtab().
   421  */
   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 */
   429  ){
   430    return fts5InitVtab(0, db, pAux, argc, argv, ppVtab, pzErr);
   431  }
   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 */
   439  ){
   440    return fts5InitVtab(1, db, pAux, argc, argv, ppVtab, pzErr);
   441  }
   442  
   443  /*
   444  ** The different query plans.
   445  */
   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 = ?) */
   452  
   453  /*
   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.
   457  */
   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
   463    {
   464      pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE;
   465    }
   466  #endif
   467  }
   468  
   469  /*
   470  ** Implementation of the xBestIndex method for FTS5 tables. Within the 
   471  ** WHERE constraint, it searches for the following:
   472  **
   473  **   1. A MATCH constraint against the special column.
   474  **   2. A MATCH constraint against the "rank" column.
   475  **   3. An == constraint against the rowid column.
   476  **   4. A < or <= constraint against the rowid column.
   477  **   5. A > or >= constraint against the rowid column.
   478  **
   479  ** Within the ORDER BY, either:
   480  **
   481  **   5. ORDER BY rank [ASC|DESC]
   482  **   6. ORDER BY rowid [ASC|DESC]
   483  **
   484  ** Costs are assigned as follows:
   485  **
   486  **  a) If an unusable MATCH operator is present in the WHERE clause, the
   487  **     cost is unconditionally set to 1e50 (a really big number).
   488  **
   489  **  a) If a MATCH operator is present, the cost depends on the other
   490  **     constraints also present. As follows:
   491  **
   492  **       * No other constraints:         cost=1000.0
   493  **       * One rowid range constraint:   cost=750.0
   494  **       * Both rowid range constraints: cost=500.0
   495  **       * An == rowid constraint:       cost=100.0
   496  **
   497  **  b) Otherwise, if there is no MATCH:
   498  **
   499  **       * No other constraints:         cost=1000000.0
   500  **       * One rowid range constraint:   cost=750000.0
   501  **       * Both rowid range constraints: cost=250000.0
   502  **       * An == rowid constraint:       cost=10.0
   503  **
   504  ** Costs are not modified by the ORDER BY clause.
   505  */
   506  static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
   507    Fts5Table *pTab = (Fts5Table*)pVTab;
   508    Fts5Config *pConfig = pTab->pConfig;
   509    const int nCol = pConfig->nCol;
   510    int idxFlags = 0;               /* Parameter passed through to xFilter() */
   511    int bHasMatch;
   512    int iNext;
   513    int i;
   514  
   515    struct Constraint {
   516      int op;                       /* Mask against sqlite3_index_constraint.op */
   517      int fts5op;                   /* FTS5 mask for idxFlags */
   518      int iCol;                     /* 0==rowid, 1==tbl, 2==rank */
   519      int omit;                     /* True to omit this if found */
   520      int iConsIndex;               /* Index in pInfo->aConstraint[] */
   521    } aConstraint[] = {
   522      {SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ, 
   523                                      FTS5_BI_MATCH,    1, 1, -1},
   524      {SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ, 
   525                                      FTS5_BI_RANK,     2, 1, -1},
   526      {SQLITE_INDEX_CONSTRAINT_EQ,    FTS5_BI_ROWID_EQ, 0, 0, -1},
   527      {SQLITE_INDEX_CONSTRAINT_LT|SQLITE_INDEX_CONSTRAINT_LE, 
   528                                      FTS5_BI_ROWID_LE, 0, 0, -1},
   529      {SQLITE_INDEX_CONSTRAINT_GT|SQLITE_INDEX_CONSTRAINT_GE, 
   530                                      FTS5_BI_ROWID_GE, 0, 0, -1},
   531    };
   532  
   533    int aColMap[3];
   534    aColMap[0] = -1;
   535    aColMap[1] = nCol;
   536    aColMap[2] = nCol+1;
   537  
   538    /* Set idxFlags flags for all WHERE clause terms that will be used. */
   539    for(i=0; i<pInfo->nConstraint; i++){
   540      struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
   541      int iCol = p->iColumn;
   542  
   543      if( (p->op==SQLITE_INDEX_CONSTRAINT_MATCH && iCol>=0 && iCol<=nCol)
   544       || (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol==nCol)
   545      ){
   546        /* A MATCH operator or equivalent */
   547        if( p->usable ){
   548          idxFlags = (idxFlags & 0xFFFF) | FTS5_BI_MATCH | (iCol << 16);
   549          aConstraint[0].iConsIndex = i;
   550        }else{
   551          /* As there exists an unusable MATCH constraint this is an 
   552          ** unusable plan. Set a prohibitively high cost. */
   553          pInfo->estimatedCost = 1e50;
   554          return SQLITE_OK;
   555        }
   556      }else{
   557        int j;
   558        for(j=1; j<ArraySize(aConstraint); j++){
   559          struct Constraint *pC = &aConstraint[j];
   560          if( iCol==aColMap[pC->iCol] && p->op & pC->op && p->usable ){
   561            pC->iConsIndex = i;
   562            idxFlags |= pC->fts5op;
   563          }
   564        }
   565      }
   566    }
   567  
   568    /* Set idxFlags flags for the ORDER BY clause */
   569    if( pInfo->nOrderBy==1 ){
   570      int iSort = pInfo->aOrderBy[0].iColumn;
   571      if( iSort==(pConfig->nCol+1) && BitFlagTest(idxFlags, FTS5_BI_MATCH) ){
   572        idxFlags |= FTS5_BI_ORDER_RANK;
   573      }else if( iSort==-1 ){
   574        idxFlags |= FTS5_BI_ORDER_ROWID;
   575      }
   576      if( BitFlagTest(idxFlags, FTS5_BI_ORDER_RANK|FTS5_BI_ORDER_ROWID) ){
   577        pInfo->orderByConsumed = 1;
   578        if( pInfo->aOrderBy[0].desc ){
   579          idxFlags |= FTS5_BI_ORDER_DESC;
   580        }
   581      }
   582    }
   583  
   584    /* Calculate the estimated cost based on the flags set in idxFlags. */
   585    bHasMatch = BitFlagTest(idxFlags, FTS5_BI_MATCH);
   586    if( BitFlagTest(idxFlags, FTS5_BI_ROWID_EQ) ){
   587      pInfo->estimatedCost = bHasMatch ? 100.0 : 10.0;
   588      if( bHasMatch==0 ) fts5SetUniqueFlag(pInfo);
   589    }else if( BitFlagAllTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){
   590      pInfo->estimatedCost = bHasMatch ? 500.0 : 250000.0;
   591    }else if( BitFlagTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){
   592      pInfo->estimatedCost = bHasMatch ? 750.0 : 750000.0;
   593    }else{
   594      pInfo->estimatedCost = bHasMatch ? 1000.0 : 1000000.0;
   595    }
   596  
   597    /* Assign argvIndex values to each constraint in use. */
   598    iNext = 1;
   599    for(i=0; i<ArraySize(aConstraint); i++){
   600      struct Constraint *pC = &aConstraint[i];
   601      if( pC->iConsIndex>=0 ){
   602        pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++;
   603        pInfo->aConstraintUsage[pC->iConsIndex].omit = (unsigned char)pC->omit;
   604      }
   605    }
   606  
   607    pInfo->idxNum = idxFlags;
   608    return SQLITE_OK;
   609  }
   610  
   611  static int fts5NewTransaction(Fts5Table *pTab){
   612    Fts5Cursor *pCsr;
   613    for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
   614      if( pCsr->base.pVtab==(sqlite3_vtab*)pTab ) return SQLITE_OK;
   615    }
   616    return sqlite3Fts5StorageReset(pTab->pStorage);
   617  }
   618  
   619  /*
   620  ** Implementation of xOpen method.
   621  */
   622  static int fts5OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
   623    Fts5Table *pTab = (Fts5Table*)pVTab;
   624    Fts5Config *pConfig = pTab->pConfig;
   625    Fts5Cursor *pCsr = 0;           /* New cursor object */
   626    int nByte;                      /* Bytes of space to allocate */
   627    int rc;                         /* Return code */
   628  
   629    rc = fts5NewTransaction(pTab);
   630    if( rc==SQLITE_OK ){
   631      nByte = sizeof(Fts5Cursor) + pConfig->nCol * sizeof(int);
   632      pCsr = (Fts5Cursor*)sqlite3_malloc(nByte);
   633      if( pCsr ){
   634        Fts5Global *pGlobal = pTab->pGlobal;
   635        memset(pCsr, 0, nByte);
   636        pCsr->aColumnSize = (int*)&pCsr[1];
   637        pCsr->pNext = pGlobal->pCsr;
   638        pGlobal->pCsr = pCsr;
   639        pCsr->iCsrId = ++pGlobal->iNextId;
   640      }else{
   641        rc = SQLITE_NOMEM;
   642      }
   643    }
   644    *ppCsr = (sqlite3_vtab_cursor*)pCsr;
   645    return rc;
   646  }
   647  
   648  static int fts5StmtType(Fts5Cursor *pCsr){
   649    if( pCsr->ePlan==FTS5_PLAN_SCAN ){
   650      return (pCsr->bDesc) ? FTS5_STMT_SCAN_DESC : FTS5_STMT_SCAN_ASC;
   651    }
   652    return FTS5_STMT_LOOKUP;
   653  }
   654  
   655  /*
   656  ** This function is called after the cursor passed as the only argument
   657  ** is moved to point at a different row. It clears all cached data 
   658  ** specific to the previous row stored by the cursor object.
   659  */
   660  static void fts5CsrNewrow(Fts5Cursor *pCsr){
   661    CsrFlagSet(pCsr, 
   662        FTS5CSR_REQUIRE_CONTENT 
   663      | FTS5CSR_REQUIRE_DOCSIZE 
   664      | FTS5CSR_REQUIRE_INST 
   665      | FTS5CSR_REQUIRE_POSLIST 
   666    );
   667  }
   668  
   669  static void fts5FreeCursorComponents(Fts5Cursor *pCsr){
   670    Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
   671    Fts5Auxdata *pData;
   672    Fts5Auxdata *pNext;
   673  
   674    sqlite3_free(pCsr->aInstIter);
   675    sqlite3_free(pCsr->aInst);
   676    if( pCsr->pStmt ){
   677      int eStmt = fts5StmtType(pCsr);
   678      sqlite3Fts5StorageStmtRelease(pTab->pStorage, eStmt, pCsr->pStmt);
   679    }
   680    if( pCsr->pSorter ){
   681      Fts5Sorter *pSorter = pCsr->pSorter;
   682      sqlite3_finalize(pSorter->pStmt);
   683      sqlite3_free(pSorter);
   684    }
   685  
   686    if( pCsr->ePlan!=FTS5_PLAN_SOURCE ){
   687      sqlite3Fts5ExprFree(pCsr->pExpr);
   688    }
   689  
   690    for(pData=pCsr->pAuxdata; pData; pData=pNext){
   691      pNext = pData->pNext;
   692      if( pData->xDelete ) pData->xDelete(pData->pPtr);
   693      sqlite3_free(pData);
   694    }
   695  
   696    sqlite3_finalize(pCsr->pRankArgStmt);
   697    sqlite3_free(pCsr->apRankArg);
   698  
   699    if( CsrFlagTest(pCsr, FTS5CSR_FREE_ZRANK) ){
   700      sqlite3_free(pCsr->zRank);
   701      sqlite3_free(pCsr->zRankArgs);
   702    }
   703  
   704    memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan - (u8*)pCsr));
   705  }
   706  
   707  
   708  /*
   709  ** Close the cursor.  For additional information see the documentation
   710  ** on the xClose method of the virtual table interface.
   711  */
   712  static int fts5CloseMethod(sqlite3_vtab_cursor *pCursor){
   713    if( pCursor ){
   714      Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
   715      Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
   716      Fts5Cursor **pp;
   717  
   718      fts5FreeCursorComponents(pCsr);
   719      /* Remove the cursor from the Fts5Global.pCsr list */
   720      for(pp=&pTab->pGlobal->pCsr; (*pp)!=pCsr; pp=&(*pp)->pNext);
   721      *pp = pCsr->pNext;
   722  
   723      sqlite3_free(pCsr);
   724    }
   725    return SQLITE_OK;
   726  }
   727  
   728  static int fts5SorterNext(Fts5Cursor *pCsr){
   729    Fts5Sorter *pSorter = pCsr->pSorter;
   730    int rc;
   731  
   732    rc = sqlite3_step(pSorter->pStmt);
   733    if( rc==SQLITE_DONE ){
   734      rc = SQLITE_OK;
   735      CsrFlagSet(pCsr, FTS5CSR_EOF);
   736    }else if( rc==SQLITE_ROW ){
   737      const u8 *a;
   738      const u8 *aBlob;
   739      int nBlob;
   740      int i;
   741      int iOff = 0;
   742      rc = SQLITE_OK;
   743  
   744      pSorter->iRowid = sqlite3_column_int64(pSorter->pStmt, 0);
   745      nBlob = sqlite3_column_bytes(pSorter->pStmt, 1);
   746      aBlob = a = sqlite3_column_blob(pSorter->pStmt, 1);
   747  
   748      /* nBlob==0 in detail=none mode. */
   749      if( nBlob>0 ){
   750        for(i=0; i<(pSorter->nIdx-1); i++){
   751          int iVal;
   752          a += fts5GetVarint32(a, iVal);
   753          iOff += iVal;
   754          pSorter->aIdx[i] = iOff;
   755        }
   756        pSorter->aIdx[i] = &aBlob[nBlob] - a;
   757        pSorter->aPoslist = a;
   758      }
   759  
   760      fts5CsrNewrow(pCsr);
   761    }
   762  
   763    return rc;
   764  }
   765  
   766  
   767  /*
   768  ** Set the FTS5CSR_REQUIRE_RESEEK flag on all FTS5_PLAN_MATCH cursors 
   769  ** open on table pTab.
   770  */
   771  static void fts5TripCursors(Fts5Table *pTab){
   772    Fts5Cursor *pCsr;
   773    for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
   774      if( pCsr->ePlan==FTS5_PLAN_MATCH
   775       && pCsr->base.pVtab==(sqlite3_vtab*)pTab 
   776      ){
   777        CsrFlagSet(pCsr, FTS5CSR_REQUIRE_RESEEK);
   778      }
   779    }
   780  }
   781  
   782  /*
   783  ** If the REQUIRE_RESEEK flag is set on the cursor passed as the first
   784  ** argument, close and reopen all Fts5IndexIter iterators that the cursor 
   785  ** is using. Then attempt to move the cursor to a rowid equal to or laster
   786  ** (in the cursors sort order - ASC or DESC) than the current rowid. 
   787  **
   788  ** If the new rowid is not equal to the old, set output parameter *pbSkip
   789  ** to 1 before returning. Otherwise, leave it unchanged.
   790  **
   791  ** Return SQLITE_OK if successful or if no reseek was required, or an 
   792  ** error code if an error occurred.
   793  */
   794  static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){
   795    int rc = SQLITE_OK;
   796    assert( *pbSkip==0 );
   797    if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_RESEEK) ){
   798      Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
   799      int bDesc = pCsr->bDesc;
   800      i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr);
   801  
   802      rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->pIndex, iRowid, bDesc);
   803      if( rc==SQLITE_OK &&  iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){
   804        *pbSkip = 1;
   805      }
   806  
   807      CsrFlagClear(pCsr, FTS5CSR_REQUIRE_RESEEK);
   808      fts5CsrNewrow(pCsr);
   809      if( sqlite3Fts5ExprEof(pCsr->pExpr) ){
   810        CsrFlagSet(pCsr, FTS5CSR_EOF);
   811        *pbSkip = 1;
   812      }
   813    }
   814    return rc;
   815  }
   816  
   817  
   818  /*
   819  ** Advance the cursor to the next row in the table that matches the 
   820  ** search criteria.
   821  **
   822  ** Return SQLITE_OK if nothing goes wrong.  SQLITE_OK is returned
   823  ** even if we reach end-of-file.  The fts5EofMethod() will be called
   824  ** subsequently to determine whether or not an EOF was hit.
   825  */
   826  static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){
   827    Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
   828    int rc;
   829  
   830    assert( (pCsr->ePlan<3)==
   831            (pCsr->ePlan==FTS5_PLAN_MATCH || pCsr->ePlan==FTS5_PLAN_SOURCE) 
   832    );
   833    assert( !CsrFlagTest(pCsr, FTS5CSR_EOF) );
   834  
   835    if( pCsr->ePlan<3 ){
   836      int bSkip = 0;
   837      if( (rc = fts5CursorReseek(pCsr, &bSkip)) || bSkip ) return rc;
   838      rc = sqlite3Fts5ExprNext(pCsr->pExpr, pCsr->iLastRowid);
   839      CsrFlagSet(pCsr, sqlite3Fts5ExprEof(pCsr->pExpr));
   840      fts5CsrNewrow(pCsr);
   841    }else{
   842      switch( pCsr->ePlan ){
   843        case FTS5_PLAN_SPECIAL: {
   844          CsrFlagSet(pCsr, FTS5CSR_EOF);
   845          rc = SQLITE_OK;
   846          break;
   847        }
   848    
   849        case FTS5_PLAN_SORTED_MATCH: {
   850          rc = fts5SorterNext(pCsr);
   851          break;
   852        }
   853    
   854        default:
   855          rc = sqlite3_step(pCsr->pStmt);
   856          if( rc!=SQLITE_ROW ){
   857            CsrFlagSet(pCsr, FTS5CSR_EOF);
   858            rc = sqlite3_reset(pCsr->pStmt);
   859          }else{
   860            rc = SQLITE_OK;
   861          }
   862          break;
   863      }
   864    }
   865    
   866    return rc;
   867  }
   868  
   869  
   870  static int fts5PrepareStatement(
   871    sqlite3_stmt **ppStmt,
   872    Fts5Config *pConfig, 
   873    const char *zFmt,
   874    ...
   875  ){
   876    sqlite3_stmt *pRet = 0;
   877    int rc;
   878    char *zSql;
   879    va_list ap;
   880  
   881    va_start(ap, zFmt);
   882    zSql = sqlite3_vmprintf(zFmt, ap);
   883    if( zSql==0 ){
   884      rc = SQLITE_NOMEM; 
   885    }else{
   886      rc = sqlite3_prepare_v3(pConfig->db, zSql, -1, 
   887                              SQLITE_PREPARE_PERSISTENT, &pRet, 0);
   888      if( rc!=SQLITE_OK ){
   889        *pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db));
   890      }
   891      sqlite3_free(zSql);
   892    }
   893  
   894    va_end(ap);
   895    *ppStmt = pRet;
   896    return rc;
   897  } 
   898  
   899  static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
   900    Fts5Config *pConfig = pTab->pConfig;
   901    Fts5Sorter *pSorter;
   902    int nPhrase;
   903    int nByte;
   904    int rc;
   905    const char *zRank = pCsr->zRank;
   906    const char *zRankArgs = pCsr->zRankArgs;
   907    
   908    nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
   909    nByte = sizeof(Fts5Sorter) + sizeof(int) * (nPhrase-1);
   910    pSorter = (Fts5Sorter*)sqlite3_malloc(nByte);
   911    if( pSorter==0 ) return SQLITE_NOMEM;
   912    memset(pSorter, 0, nByte);
   913    pSorter->nIdx = nPhrase;
   914  
   915    /* TODO: It would be better to have some system for reusing statement
   916    ** handles here, rather than preparing a new one for each query. But that
   917    ** is not possible as SQLite reference counts the virtual table objects.
   918    ** And since the statement required here reads from this very virtual 
   919    ** table, saving it creates a circular reference.
   920    **
   921    ** If SQLite a built-in statement cache, this wouldn't be a problem. */
   922    rc = fts5PrepareStatement(&pSorter->pStmt, pConfig,
   923        "SELECT rowid, rank FROM %Q.%Q ORDER BY %s(%s%s%s) %s",
   924        pConfig->zDb, pConfig->zName, zRank, pConfig->zName,
   925        (zRankArgs ? ", " : ""),
   926        (zRankArgs ? zRankArgs : ""),
   927        bDesc ? "DESC" : "ASC"
   928    );
   929  
   930    pCsr->pSorter = pSorter;
   931    if( rc==SQLITE_OK ){
   932      assert( pTab->pSortCsr==0 );
   933      pTab->pSortCsr = pCsr;
   934      rc = fts5SorterNext(pCsr);
   935      pTab->pSortCsr = 0;
   936    }
   937  
   938    if( rc!=SQLITE_OK ){
   939      sqlite3_finalize(pSorter->pStmt);
   940      sqlite3_free(pSorter);
   941      pCsr->pSorter = 0;
   942    }
   943  
   944    return rc;
   945  }
   946  
   947  static int fts5CursorFirst(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
   948    int rc;
   949    Fts5Expr *pExpr = pCsr->pExpr;
   950    rc = sqlite3Fts5ExprFirst(pExpr, pTab->pIndex, pCsr->iFirstRowid, bDesc);
   951    if( sqlite3Fts5ExprEof(pExpr) ){
   952      CsrFlagSet(pCsr, FTS5CSR_EOF);
   953    }
   954    fts5CsrNewrow(pCsr);
   955    return rc;
   956  }
   957  
   958  /*
   959  ** Process a "special" query. A special query is identified as one with a
   960  ** MATCH expression that begins with a '*' character. The remainder of
   961  ** the text passed to the MATCH operator are used as  the special query
   962  ** parameters.
   963  */
   964  static int fts5SpecialMatch(
   965    Fts5Table *pTab, 
   966    Fts5Cursor *pCsr, 
   967    const char *zQuery
   968  ){
   969    int rc = SQLITE_OK;             /* Return code */
   970    const char *z = zQuery;         /* Special query text */
   971    int n;                          /* Number of bytes in text at z */
   972  
   973    while( z[0]==' ' ) z++;
   974    for(n=0; z[n] && z[n]!=' '; n++);
   975  
   976    assert( pTab->base.zErrMsg==0 );
   977    pCsr->ePlan = FTS5_PLAN_SPECIAL;
   978  
   979    if( 0==sqlite3_strnicmp("reads", z, n) ){
   980      pCsr->iSpecial = sqlite3Fts5IndexReads(pTab->pIndex);
   981    }
   982    else if( 0==sqlite3_strnicmp("id", z, n) ){
   983      pCsr->iSpecial = pCsr->iCsrId;
   984    }
   985    else{
   986      /* An unrecognized directive. Return an error message. */
   987      pTab->base.zErrMsg = sqlite3_mprintf("unknown special query: %.*s", n, z);
   988      rc = SQLITE_ERROR;
   989    }
   990  
   991    return rc;
   992  }
   993  
   994  /*
   995  ** Search for an auxiliary function named zName that can be used with table
   996  ** pTab. If one is found, return a pointer to the corresponding Fts5Auxiliary
   997  ** structure. Otherwise, if no such function exists, return NULL.
   998  */
   999  static Fts5Auxiliary *fts5FindAuxiliary(Fts5Table *pTab, const char *zName){
  1000    Fts5Auxiliary *pAux;
  1001  
  1002    for(pAux=pTab->pGlobal->pAux; pAux; pAux=pAux->pNext){
  1003      if( sqlite3_stricmp(zName, pAux->zFunc)==0 ) return pAux;
  1004    }
  1005  
  1006    /* No function of the specified name was found. Return 0. */
  1007    return 0;
  1008  }
  1009  
  1010  
  1011  static int fts5FindRankFunction(Fts5Cursor *pCsr){
  1012    Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
  1013    Fts5Config *pConfig = pTab->pConfig;
  1014    int rc = SQLITE_OK;
  1015    Fts5Auxiliary *pAux = 0;
  1016    const char *zRank = pCsr->zRank;
  1017    const char *zRankArgs = pCsr->zRankArgs;
  1018  
  1019    if( zRankArgs ){
  1020      char *zSql = sqlite3Fts5Mprintf(&rc, "SELECT %s", zRankArgs);
  1021      if( zSql ){
  1022        sqlite3_stmt *pStmt = 0;
  1023        rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
  1024                                SQLITE_PREPARE_PERSISTENT, &pStmt, 0);
  1025        sqlite3_free(zSql);
  1026        assert( rc==SQLITE_OK || pCsr->pRankArgStmt==0 );
  1027        if( rc==SQLITE_OK ){
  1028          if( SQLITE_ROW==sqlite3_step(pStmt) ){
  1029            int nByte;
  1030            pCsr->nRankArg = sqlite3_column_count(pStmt);
  1031            nByte = sizeof(sqlite3_value*)*pCsr->nRankArg;
  1032            pCsr->apRankArg = (sqlite3_value**)sqlite3Fts5MallocZero(&rc, nByte);
  1033            if( rc==SQLITE_OK ){
  1034              int i;
  1035              for(i=0; i<pCsr->nRankArg; i++){
  1036                pCsr->apRankArg[i] = sqlite3_column_value(pStmt, i);
  1037              }
  1038            }
  1039            pCsr->pRankArgStmt = pStmt;
  1040          }else{
  1041            rc = sqlite3_finalize(pStmt);
  1042            assert( rc!=SQLITE_OK );
  1043          }
  1044        }
  1045      }
  1046    }
  1047  
  1048    if( rc==SQLITE_OK ){
  1049      pAux = fts5FindAuxiliary(pTab, zRank);
  1050      if( pAux==0 ){
  1051        assert( pTab->base.zErrMsg==0 );
  1052        pTab->base.zErrMsg = sqlite3_mprintf("no such function: %s", zRank);
  1053        rc = SQLITE_ERROR;
  1054      }
  1055    }
  1056  
  1057    pCsr->pRank = pAux;
  1058    return rc;
  1059  }
  1060  
  1061  
  1062  static int fts5CursorParseRank(
  1063    Fts5Config *pConfig,
  1064    Fts5Cursor *pCsr, 
  1065    sqlite3_value *pRank
  1066  ){
  1067    int rc = SQLITE_OK;
  1068    if( pRank ){
  1069      const char *z = (const char*)sqlite3_value_text(pRank);
  1070      char *zRank = 0;
  1071      char *zRankArgs = 0;
  1072  
  1073      if( z==0 ){
  1074        if( sqlite3_value_type(pRank)==SQLITE_NULL ) rc = SQLITE_ERROR;
  1075      }else{
  1076        rc = sqlite3Fts5ConfigParseRank(z, &zRank, &zRankArgs);
  1077      }
  1078      if( rc==SQLITE_OK ){
  1079        pCsr->zRank = zRank;
  1080        pCsr->zRankArgs = zRankArgs;
  1081        CsrFlagSet(pCsr, FTS5CSR_FREE_ZRANK);
  1082      }else if( rc==SQLITE_ERROR ){
  1083        pCsr->base.pVtab->zErrMsg = sqlite3_mprintf(
  1084            "parse error in rank function: %s", z
  1085        );
  1086      }
  1087    }else{
  1088      if( pConfig->zRank ){
  1089        pCsr->zRank = (char*)pConfig->zRank;
  1090        pCsr->zRankArgs = (char*)pConfig->zRankArgs;
  1091      }else{
  1092        pCsr->zRank = (char*)FTS5_DEFAULT_RANK;
  1093        pCsr->zRankArgs = 0;
  1094      }
  1095    }
  1096    return rc;
  1097  }
  1098  
  1099  static i64 fts5GetRowidLimit(sqlite3_value *pVal, i64 iDefault){
  1100    if( pVal ){
  1101      int eType = sqlite3_value_numeric_type(pVal);
  1102      if( eType==SQLITE_INTEGER ){
  1103        return sqlite3_value_int64(pVal);
  1104      }
  1105    }
  1106    return iDefault;
  1107  }
  1108  
  1109  /*
  1110  ** This is the xFilter interface for the virtual table.  See
  1111  ** the virtual table xFilter method documentation for additional
  1112  ** information.
  1113  ** 
  1114  ** There are three possible query strategies:
  1115  **
  1116  **   1. Full-text search using a MATCH operator.
  1117  **   2. A by-rowid lookup.
  1118  **   3. A full-table scan.
  1119  */
  1120  static int fts5FilterMethod(
  1121    sqlite3_vtab_cursor *pCursor,   /* The cursor used for this query */
  1122    int idxNum,                     /* Strategy index */
  1123    const char *zUnused,            /* Unused */
  1124    int nVal,                       /* Number of elements in apVal */
  1125    sqlite3_value **apVal           /* Arguments for the indexing scheme */
  1126  ){
  1127    Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
  1128    Fts5Config *pConfig = pTab->pConfig;
  1129    Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
  1130    int rc = SQLITE_OK;             /* Error code */
  1131    int iVal = 0;                   /* Counter for apVal[] */
  1132    int bDesc;                      /* True if ORDER BY [rank|rowid] DESC */
  1133    int bOrderByRank;               /* True if ORDER BY rank */
  1134    sqlite3_value *pMatch = 0;      /* <tbl> MATCH ? expression (or NULL) */
  1135    sqlite3_value *pRank = 0;       /* rank MATCH ? expression (or NULL) */
  1136    sqlite3_value *pRowidEq = 0;    /* rowid = ? expression (or NULL) */
  1137    sqlite3_value *pRowidLe = 0;    /* rowid <= ? expression (or NULL) */
  1138    sqlite3_value *pRowidGe = 0;    /* rowid >= ? expression (or NULL) */
  1139    int iCol;                       /* Column on LHS of MATCH operator */
  1140    char **pzErrmsg = pConfig->pzErrmsg;
  1141  
  1142    UNUSED_PARAM(zUnused);
  1143    UNUSED_PARAM(nVal);
  1144  
  1145    if( pCsr->ePlan ){
  1146      fts5FreeCursorComponents(pCsr);
  1147      memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan-(u8*)pCsr));
  1148    }
  1149  
  1150    assert( pCsr->pStmt==0 );
  1151    assert( pCsr->pExpr==0 );
  1152    assert( pCsr->csrflags==0 );
  1153    assert( pCsr->pRank==0 );
  1154    assert( pCsr->zRank==0 );
  1155    assert( pCsr->zRankArgs==0 );
  1156  
  1157    assert( pzErrmsg==0 || pzErrmsg==&pTab->base.zErrMsg );
  1158    pConfig->pzErrmsg = &pTab->base.zErrMsg;
  1159  
  1160    /* Decode the arguments passed through to this function.
  1161    **
  1162    ** Note: The following set of if(...) statements must be in the same
  1163    ** order as the corresponding entries in the struct at the top of
  1164    ** fts5BestIndexMethod().  */
  1165    if( BitFlagTest(idxNum, FTS5_BI_MATCH) ) pMatch = apVal[iVal++];
  1166    if( BitFlagTest(idxNum, FTS5_BI_RANK) ) pRank = apVal[iVal++];
  1167    if( BitFlagTest(idxNum, FTS5_BI_ROWID_EQ) ) pRowidEq = apVal[iVal++];
  1168    if( BitFlagTest(idxNum, FTS5_BI_ROWID_LE) ) pRowidLe = apVal[iVal++];
  1169    if( BitFlagTest(idxNum, FTS5_BI_ROWID_GE) ) pRowidGe = apVal[iVal++];
  1170    iCol = (idxNum>>16);
  1171    assert( iCol>=0 && iCol<=pConfig->nCol );
  1172    assert( iVal==nVal );
  1173    bOrderByRank = ((idxNum & FTS5_BI_ORDER_RANK) ? 1 : 0);
  1174    pCsr->bDesc = bDesc = ((idxNum & FTS5_BI_ORDER_DESC) ? 1 : 0);
  1175  
  1176    /* Set the cursor upper and lower rowid limits. Only some strategies 
  1177    ** actually use them. This is ok, as the xBestIndex() method leaves the
  1178    ** sqlite3_index_constraint.omit flag clear for range constraints
  1179    ** on the rowid field.  */
  1180    if( pRowidEq ){
  1181      pRowidLe = pRowidGe = pRowidEq;
  1182    }
  1183    if( bDesc ){
  1184      pCsr->iFirstRowid = fts5GetRowidLimit(pRowidLe, LARGEST_INT64);
  1185      pCsr->iLastRowid = fts5GetRowidLimit(pRowidGe, SMALLEST_INT64);
  1186    }else{
  1187      pCsr->iLastRowid = fts5GetRowidLimit(pRowidLe, LARGEST_INT64);
  1188      pCsr->iFirstRowid = fts5GetRowidLimit(pRowidGe, SMALLEST_INT64);
  1189    }
  1190  
  1191    if( pTab->pSortCsr ){
  1192      /* If pSortCsr is non-NULL, then this call is being made as part of 
  1193      ** processing for a "... MATCH <expr> ORDER BY rank" query (ePlan is
  1194      ** set to FTS5_PLAN_SORTED_MATCH). pSortCsr is the cursor that will
  1195      ** return results to the user for this query. The current cursor 
  1196      ** (pCursor) is used to execute the query issued by function 
  1197      ** fts5CursorFirstSorted() above.  */
  1198      assert( pRowidEq==0 && pRowidLe==0 && pRowidGe==0 && pRank==0 );
  1199      assert( nVal==0 && pMatch==0 && bOrderByRank==0 && bDesc==0 );
  1200      assert( pCsr->iLastRowid==LARGEST_INT64 );
  1201      assert( pCsr->iFirstRowid==SMALLEST_INT64 );
  1202      pCsr->ePlan = FTS5_PLAN_SOURCE;
  1203      pCsr->pExpr = pTab->pSortCsr->pExpr;
  1204      rc = fts5CursorFirst(pTab, pCsr, bDesc);
  1205    }else if( pMatch ){
  1206      const char *zExpr = (const char*)sqlite3_value_text(apVal[0]);
  1207      if( zExpr==0 ) zExpr = "";
  1208  
  1209      rc = fts5CursorParseRank(pConfig, pCsr, pRank);
  1210      if( rc==SQLITE_OK ){
  1211        if( zExpr[0]=='*' ){
  1212          /* The user has issued a query of the form "MATCH '*...'". This
  1213          ** indicates that the MATCH expression is not a full text query,
  1214          ** but a request for an internal parameter.  */
  1215          rc = fts5SpecialMatch(pTab, pCsr, &zExpr[1]);
  1216        }else{
  1217          char **pzErr = &pTab->base.zErrMsg;
  1218          rc = sqlite3Fts5ExprNew(pConfig, iCol, zExpr, &pCsr->pExpr, pzErr);
  1219          if( rc==SQLITE_OK ){
  1220            if( bOrderByRank ){
  1221              pCsr->ePlan = FTS5_PLAN_SORTED_MATCH;
  1222              rc = fts5CursorFirstSorted(pTab, pCsr, bDesc);
  1223            }else{
  1224              pCsr->ePlan = FTS5_PLAN_MATCH;
  1225              rc = fts5CursorFirst(pTab, pCsr, bDesc);
  1226            }
  1227          }
  1228        }
  1229      }
  1230    }else if( pConfig->zContent==0 ){
  1231      *pConfig->pzErrmsg = sqlite3_mprintf(
  1232          "%s: table does not support scanning", pConfig->zName
  1233      );
  1234      rc = SQLITE_ERROR;
  1235    }else{
  1236      /* This is either a full-table scan (ePlan==FTS5_PLAN_SCAN) or a lookup
  1237      ** by rowid (ePlan==FTS5_PLAN_ROWID).  */
  1238      pCsr->ePlan = (pRowidEq ? FTS5_PLAN_ROWID : FTS5_PLAN_SCAN);
  1239      rc = sqlite3Fts5StorageStmt(
  1240          pTab->pStorage, fts5StmtType(pCsr), &pCsr->pStmt, &pTab->base.zErrMsg
  1241      );
  1242      if( rc==SQLITE_OK ){
  1243        if( pCsr->ePlan==FTS5_PLAN_ROWID ){
  1244          sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
  1245        }else{
  1246          sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iFirstRowid);
  1247          sqlite3_bind_int64(pCsr->pStmt, 2, pCsr->iLastRowid);
  1248        }
  1249        rc = fts5NextMethod(pCursor);
  1250      }
  1251    }
  1252  
  1253    pConfig->pzErrmsg = pzErrmsg;
  1254    return rc;
  1255  }
  1256  
  1257  /* 
  1258  ** This is the xEof method of the virtual table. SQLite calls this 
  1259  ** routine to find out if it has reached the end of a result set.
  1260  */
  1261  static int fts5EofMethod(sqlite3_vtab_cursor *pCursor){
  1262    Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
  1263    return (CsrFlagTest(pCsr, FTS5CSR_EOF) ? 1 : 0);
  1264  }
  1265  
  1266  /*
  1267  ** Return the rowid that the cursor currently points to.
  1268  */
  1269  static i64 fts5CursorRowid(Fts5Cursor *pCsr){
  1270    assert( pCsr->ePlan==FTS5_PLAN_MATCH 
  1271         || pCsr->ePlan==FTS5_PLAN_SORTED_MATCH 
  1272         || pCsr->ePlan==FTS5_PLAN_SOURCE 
  1273    );
  1274    if( pCsr->pSorter ){
  1275      return pCsr->pSorter->iRowid;
  1276    }else{
  1277      return sqlite3Fts5ExprRowid(pCsr->pExpr);
  1278    }
  1279  }
  1280  
  1281  /* 
  1282  ** This is the xRowid method. The SQLite core calls this routine to
  1283  ** retrieve the rowid for the current row of the result set. fts5
  1284  ** exposes %_content.rowid as the rowid for the virtual table. The
  1285  ** rowid should be written to *pRowid.
  1286  */
  1287  static int fts5RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
  1288    Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
  1289    int ePlan = pCsr->ePlan;
  1290    
  1291    assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 );
  1292    switch( ePlan ){
  1293      case FTS5_PLAN_SPECIAL:
  1294        *pRowid = 0;
  1295        break;
  1296  
  1297      case FTS5_PLAN_SOURCE:
  1298      case FTS5_PLAN_MATCH:
  1299      case FTS5_PLAN_SORTED_MATCH:
  1300        *pRowid = fts5CursorRowid(pCsr);
  1301        break;
  1302  
  1303      default:
  1304        *pRowid = sqlite3_column_int64(pCsr->pStmt, 0);
  1305        break;
  1306    }
  1307  
  1308    return SQLITE_OK;
  1309  }
  1310  
  1311  /*
  1312  ** If the cursor requires seeking (bSeekRequired flag is set), seek it.
  1313  ** Return SQLITE_OK if no error occurs, or an SQLite error code otherwise.
  1314  **
  1315  ** If argument bErrormsg is true and an error occurs, an error message may
  1316  ** be left in sqlite3_vtab.zErrMsg.
  1317  */
  1318  static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){
  1319    int rc = SQLITE_OK;
  1320  
  1321    /* If the cursor does not yet have a statement handle, obtain one now. */ 
  1322    if( pCsr->pStmt==0 ){
  1323      Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
  1324      int eStmt = fts5StmtType(pCsr);
  1325      rc = sqlite3Fts5StorageStmt(
  1326          pTab->pStorage, eStmt, &pCsr->pStmt, (bErrormsg?&pTab->base.zErrMsg:0)
  1327      );
  1328      assert( rc!=SQLITE_OK || pTab->base.zErrMsg==0 );
  1329      assert( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) );
  1330    }
  1331  
  1332    if( rc==SQLITE_OK && CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) ){
  1333      assert( pCsr->pExpr );
  1334      sqlite3_reset(pCsr->pStmt);
  1335      sqlite3_bind_int64(pCsr->pStmt, 1, fts5CursorRowid(pCsr));
  1336      rc = sqlite3_step(pCsr->pStmt);
  1337      if( rc==SQLITE_ROW ){
  1338        rc = SQLITE_OK;
  1339        CsrFlagClear(pCsr, FTS5CSR_REQUIRE_CONTENT);
  1340      }else{
  1341        rc = sqlite3_reset(pCsr->pStmt);
  1342        if( rc==SQLITE_OK ){
  1343          rc = FTS5_CORRUPT;
  1344        }
  1345      }
  1346    }
  1347    return rc;
  1348  }
  1349  
  1350  static void fts5SetVtabError(Fts5Table *p, const char *zFormat, ...){
  1351    va_list ap;                     /* ... printf arguments */
  1352    va_start(ap, zFormat);
  1353    assert( p->base.zErrMsg==0 );
  1354    p->base.zErrMsg = sqlite3_vmprintf(zFormat, ap);
  1355    va_end(ap);
  1356  }
  1357  
  1358  /*
  1359  ** This function is called to handle an FTS INSERT command. In other words,
  1360  ** an INSERT statement of the form:
  1361  **
  1362  **     INSERT INTO fts(fts) VALUES($pCmd)
  1363  **     INSERT INTO fts(fts, rank) VALUES($pCmd, $pVal)
  1364  **
  1365  ** Argument pVal is the value assigned to column "fts" by the INSERT 
  1366  ** statement. This function returns SQLITE_OK if successful, or an SQLite
  1367  ** error code if an error occurs.
  1368  **
  1369  ** The commands implemented by this function are documented in the "Special
  1370  ** INSERT Directives" section of the documentation. It should be updated if
  1371  ** more commands are added to this function.
  1372  */
  1373  static int fts5SpecialInsert(
  1374    Fts5Table *pTab,                /* Fts5 table object */
  1375    const char *zCmd,               /* Text inserted into table-name column */
  1376    sqlite3_value *pVal             /* Value inserted into rank column */
  1377  ){
  1378    Fts5Config *pConfig = pTab->pConfig;
  1379    int rc = SQLITE_OK;
  1380    int bError = 0;
  1381  
  1382    if( 0==sqlite3_stricmp("delete-all", zCmd) ){
  1383      if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
  1384        fts5SetVtabError(pTab, 
  1385            "'delete-all' may only be used with a "
  1386            "contentless or external content fts5 table"
  1387        );
  1388        rc = SQLITE_ERROR;
  1389      }else{
  1390        rc = sqlite3Fts5StorageDeleteAll(pTab->pStorage);
  1391      }
  1392    }else if( 0==sqlite3_stricmp("rebuild", zCmd) ){
  1393      if( pConfig->eContent==FTS5_CONTENT_NONE ){
  1394        fts5SetVtabError(pTab, 
  1395            "'rebuild' may not be used with a contentless fts5 table"
  1396        );
  1397        rc = SQLITE_ERROR;
  1398      }else{
  1399        rc = sqlite3Fts5StorageRebuild(pTab->pStorage);
  1400      }
  1401    }else if( 0==sqlite3_stricmp("optimize", zCmd) ){
  1402      rc = sqlite3Fts5StorageOptimize(pTab->pStorage);
  1403    }else if( 0==sqlite3_stricmp("merge", zCmd) ){
  1404      int nMerge = sqlite3_value_int(pVal);
  1405      rc = sqlite3Fts5StorageMerge(pTab->pStorage, nMerge);
  1406    }else if( 0==sqlite3_stricmp("integrity-check", zCmd) ){
  1407      rc = sqlite3Fts5StorageIntegrity(pTab->pStorage);
  1408  #ifdef SQLITE_DEBUG
  1409    }else if( 0==sqlite3_stricmp("prefix-index", zCmd) ){
  1410      pConfig->bPrefixIndex = sqlite3_value_int(pVal);
  1411  #endif
  1412    }else{
  1413      rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex);
  1414      if( rc==SQLITE_OK ){
  1415        rc = sqlite3Fts5ConfigSetValue(pTab->pConfig, zCmd, pVal, &bError);
  1416      }
  1417      if( rc==SQLITE_OK ){
  1418        if( bError ){
  1419          rc = SQLITE_ERROR;
  1420        }else{
  1421          rc = sqlite3Fts5StorageConfigValue(pTab->pStorage, zCmd, pVal, 0);
  1422        }
  1423      }
  1424    }
  1425    return rc;
  1426  }
  1427  
  1428  static int fts5SpecialDelete(
  1429    Fts5Table *pTab, 
  1430    sqlite3_value **apVal
  1431  ){
  1432    int rc = SQLITE_OK;
  1433    int eType1 = sqlite3_value_type(apVal[1]);
  1434    if( eType1==SQLITE_INTEGER ){
  1435      sqlite3_int64 iDel = sqlite3_value_int64(apVal[1]);
  1436      rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, &apVal[2]);
  1437    }
  1438    return rc;
  1439  }
  1440  
  1441  static void fts5StorageInsert(
  1442    int *pRc, 
  1443    Fts5Table *pTab, 
  1444    sqlite3_value **apVal, 
  1445    i64 *piRowid
  1446  ){
  1447    int rc = *pRc;
  1448    if( rc==SQLITE_OK ){
  1449      rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, piRowid);
  1450    }
  1451    if( rc==SQLITE_OK ){
  1452      rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *piRowid);
  1453    }
  1454    *pRc = rc;
  1455  }
  1456  
  1457  /* 
  1458  ** This function is the implementation of the xUpdate callback used by 
  1459  ** FTS3 virtual tables. It is invoked by SQLite each time a row is to be
  1460  ** inserted, updated or deleted.
  1461  **
  1462  ** A delete specifies a single argument - the rowid of the row to remove.
  1463  ** 
  1464  ** Update and insert operations pass:
  1465  **
  1466  **   1. The "old" rowid, or NULL.
  1467  **   2. The "new" rowid.
  1468  **   3. Values for each of the nCol matchable columns.
  1469  **   4. Values for the two hidden columns (<tablename> and "rank").
  1470  */
  1471  static int fts5UpdateMethod(
  1472    sqlite3_vtab *pVtab,            /* Virtual table handle */
  1473    int nArg,                       /* Size of argument array */
  1474    sqlite3_value **apVal,          /* Array of arguments */
  1475    sqlite_int64 *pRowid            /* OUT: The affected (or effected) rowid */
  1476  ){
  1477    Fts5Table *pTab = (Fts5Table*)pVtab;
  1478    Fts5Config *pConfig = pTab->pConfig;
  1479    int eType0;                     /* value_type() of apVal[0] */
  1480    int rc = SQLITE_OK;             /* Return code */
  1481  
  1482    /* A transaction must be open when this is called. */
  1483    assert( pTab->ts.eState==1 );
  1484  
  1485    assert( pVtab->zErrMsg==0 );
  1486    assert( nArg==1 || nArg==(2+pConfig->nCol+2) );
  1487    assert( nArg==1 
  1488        || sqlite3_value_type(apVal[1])==SQLITE_INTEGER 
  1489        || sqlite3_value_type(apVal[1])==SQLITE_NULL 
  1490    );
  1491    assert( pTab->pConfig->pzErrmsg==0 );
  1492    pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
  1493  
  1494    /* Put any active cursors into REQUIRE_SEEK state. */
  1495    fts5TripCursors(pTab);
  1496  
  1497    eType0 = sqlite3_value_type(apVal[0]);
  1498    if( eType0==SQLITE_NULL 
  1499     && sqlite3_value_type(apVal[2+pConfig->nCol])!=SQLITE_NULL 
  1500    ){
  1501      /* A "special" INSERT op. These are handled separately. */
  1502      const char *z = (const char*)sqlite3_value_text(apVal[2+pConfig->nCol]);
  1503      if( pConfig->eContent!=FTS5_CONTENT_NORMAL 
  1504        && 0==sqlite3_stricmp("delete", z) 
  1505      ){
  1506        rc = fts5SpecialDelete(pTab, apVal);
  1507      }else{
  1508        rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]);
  1509      }
  1510    }else{
  1511      /* A regular INSERT, UPDATE or DELETE statement. The trick here is that
  1512      ** any conflict on the rowid value must be detected before any 
  1513      ** modifications are made to the database file. There are 4 cases:
  1514      **
  1515      **   1) DELETE
  1516      **   2) UPDATE (rowid not modified)
  1517      **   3) UPDATE (rowid modified)
  1518      **   4) INSERT
  1519      **
  1520      ** Cases 3 and 4 may violate the rowid constraint.
  1521      */
  1522      int eConflict = SQLITE_ABORT;
  1523      if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
  1524        eConflict = sqlite3_vtab_on_conflict(pConfig->db);
  1525      }
  1526  
  1527      assert( eType0==SQLITE_INTEGER || eType0==SQLITE_NULL );
  1528      assert( nArg!=1 || eType0==SQLITE_INTEGER );
  1529  
  1530      /* Filter out attempts to run UPDATE or DELETE on contentless tables.
  1531      ** This is not suported.  */
  1532      if( eType0==SQLITE_INTEGER && fts5IsContentless(pTab) ){
  1533        pTab->base.zErrMsg = sqlite3_mprintf(
  1534            "cannot %s contentless fts5 table: %s", 
  1535            (nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName
  1536        );
  1537        rc = SQLITE_ERROR;
  1538      }
  1539  
  1540      /* DELETE */
  1541      else if( nArg==1 ){
  1542        i64 iDel = sqlite3_value_int64(apVal[0]);  /* Rowid to delete */
  1543        rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0);
  1544      }
  1545  
  1546      /* INSERT */
  1547      else if( eType0!=SQLITE_INTEGER ){     
  1548        /* If this is a REPLACE, first remove the current entry (if any) */
  1549        if( eConflict==SQLITE_REPLACE 
  1550         && sqlite3_value_type(apVal[1])==SQLITE_INTEGER 
  1551        ){
  1552          i64 iNew = sqlite3_value_int64(apVal[1]);  /* Rowid to delete */
  1553          rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
  1554        }
  1555        fts5StorageInsert(&rc, pTab, apVal, pRowid);
  1556      }
  1557  
  1558      /* UPDATE */
  1559      else{
  1560        i64 iOld = sqlite3_value_int64(apVal[0]);  /* Old rowid */
  1561        i64 iNew = sqlite3_value_int64(apVal[1]);  /* New rowid */
  1562        if( iOld!=iNew ){
  1563          if( eConflict==SQLITE_REPLACE ){
  1564            rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
  1565            if( rc==SQLITE_OK ){
  1566              rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
  1567            }
  1568            fts5StorageInsert(&rc, pTab, apVal, pRowid);
  1569          }else{
  1570            rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid);
  1571            if( rc==SQLITE_OK ){
  1572              rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
  1573            }
  1574            if( rc==SQLITE_OK ){
  1575              rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *pRowid);
  1576            }
  1577          }
  1578        }else{
  1579          rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
  1580          fts5StorageInsert(&rc, pTab, apVal, pRowid);
  1581        }
  1582      }
  1583    }
  1584  
  1585    pTab->pConfig->pzErrmsg = 0;
  1586    return rc;
  1587  }
  1588  
  1589  /*
  1590  ** Implementation of xSync() method. 
  1591  */
  1592  static int fts5SyncMethod(sqlite3_vtab *pVtab){
  1593    int rc;
  1594    Fts5Table *pTab = (Fts5Table*)pVtab;
  1595    fts5CheckTransactionState(pTab, FTS5_SYNC, 0);
  1596    pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
  1597    fts5TripCursors(pTab);
  1598    rc = sqlite3Fts5StorageSync(pTab->pStorage);
  1599    pTab->pConfig->pzErrmsg = 0;
  1600    return rc;
  1601  }
  1602  
  1603  /*
  1604  ** Implementation of xBegin() method. 
  1605  */
  1606  static int fts5BeginMethod(sqlite3_vtab *pVtab){
  1607    fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_BEGIN, 0);
  1608    fts5NewTransaction((Fts5Table*)pVtab);
  1609    return SQLITE_OK;
  1610  }
  1611  
  1612  /*
  1613  ** Implementation of xCommit() method. This is a no-op. The contents of
  1614  ** the pending-terms hash-table have already been flushed into the database
  1615  ** by fts5SyncMethod().
  1616  */
  1617  static int fts5CommitMethod(sqlite3_vtab *pVtab){
  1618    UNUSED_PARAM(pVtab);  /* Call below is a no-op for NDEBUG builds */
  1619    fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_COMMIT, 0);
  1620    return SQLITE_OK;
  1621  }
  1622  
  1623  /*
  1624  ** Implementation of xRollback(). Discard the contents of the pending-terms
  1625  ** hash-table. Any changes made to the database are reverted by SQLite.
  1626  */
  1627  static int fts5RollbackMethod(sqlite3_vtab *pVtab){
  1628    int rc;
  1629    Fts5Table *pTab = (Fts5Table*)pVtab;
  1630    fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0);
  1631    rc = sqlite3Fts5StorageRollback(pTab->pStorage);
  1632    return rc;
  1633  }
  1634  
  1635  static int fts5CsrPoslist(Fts5Cursor*, int, const u8**, int*);
  1636  
  1637  static void *fts5ApiUserData(Fts5Context *pCtx){
  1638    Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  1639    return pCsr->pAux->pUserData;
  1640  }
  1641  
  1642  static int fts5ApiColumnCount(Fts5Context *pCtx){
  1643    Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  1644    return ((Fts5Table*)(pCsr->base.pVtab))->pConfig->nCol;
  1645  }
  1646  
  1647  static int fts5ApiColumnTotalSize(
  1648    Fts5Context *pCtx, 
  1649    int iCol, 
  1650    sqlite3_int64 *pnToken
  1651  ){
  1652    Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  1653    Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
  1654    return sqlite3Fts5StorageSize(pTab->pStorage, iCol, pnToken);
  1655  }
  1656  
  1657  static int fts5ApiRowCount(Fts5Context *pCtx, i64 *pnRow){
  1658    Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  1659    Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
  1660    return sqlite3Fts5StorageRowCount(pTab->pStorage, pnRow);
  1661  }
  1662  
  1663  static int fts5ApiTokenize(
  1664    Fts5Context *pCtx, 
  1665    const char *pText, int nText, 
  1666    void *pUserData,
  1667    int (*xToken)(void*, int, const char*, int, int, int)
  1668  ){
  1669    Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  1670    Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
  1671    return sqlite3Fts5Tokenize(
  1672        pTab->pConfig, FTS5_TOKENIZE_AUX, pText, nText, pUserData, xToken
  1673    );
  1674  }
  1675  
  1676  static int fts5ApiPhraseCount(Fts5Context *pCtx){
  1677    Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  1678    return sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
  1679  }
  1680  
  1681  static int fts5ApiPhraseSize(Fts5Context *pCtx, int iPhrase){
  1682    Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  1683    return sqlite3Fts5ExprPhraseSize(pCsr->pExpr, iPhrase);
  1684  }
  1685  
  1686  static int fts5ApiColumnText(
  1687    Fts5Context *pCtx, 
  1688    int iCol, 
  1689    const char **pz, 
  1690    int *pn
  1691  ){
  1692    int rc = SQLITE_OK;
  1693    Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  1694    if( fts5IsContentless((Fts5Table*)(pCsr->base.pVtab)) ){
  1695      *pz = 0;
  1696      *pn = 0;
  1697    }else{
  1698      rc = fts5SeekCursor(pCsr, 0);
  1699      if( rc==SQLITE_OK ){
  1700        *pz = (const char*)sqlite3_column_text(pCsr->pStmt, iCol+1);
  1701        *pn = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
  1702      }
  1703    }
  1704    return rc;
  1705  }
  1706  
  1707  static int fts5CsrPoslist(
  1708    Fts5Cursor *pCsr, 
  1709    int iPhrase, 
  1710    const u8 **pa,
  1711    int *pn
  1712  ){
  1713    Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
  1714    int rc = SQLITE_OK;
  1715    int bLive = (pCsr->pSorter==0);
  1716  
  1717    if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){
  1718  
  1719      if( pConfig->eDetail!=FTS5_DETAIL_FULL ){
  1720        Fts5PoslistPopulator *aPopulator;
  1721        int i;
  1722        aPopulator = sqlite3Fts5ExprClearPoslists(pCsr->pExpr, bLive);
  1723        if( aPopulator==0 ) rc = SQLITE_NOMEM;
  1724        for(i=0; i<pConfig->nCol && rc==SQLITE_OK; i++){
  1725          int n; const char *z;
  1726          rc = fts5ApiColumnText((Fts5Context*)pCsr, i, &z, &n);
  1727          if( rc==SQLITE_OK ){
  1728            rc = sqlite3Fts5ExprPopulatePoslists(
  1729                pConfig, pCsr->pExpr, aPopulator, i, z, n
  1730            );
  1731          }
  1732        }
  1733        sqlite3_free(aPopulator);
  1734  
  1735        if( pCsr->pSorter ){
  1736          sqlite3Fts5ExprCheckPoslists(pCsr->pExpr, pCsr->pSorter->iRowid);
  1737        }
  1738      }
  1739      CsrFlagClear(pCsr, FTS5CSR_REQUIRE_POSLIST);
  1740    }
  1741  
  1742    if( pCsr->pSorter && pConfig->eDetail==FTS5_DETAIL_FULL ){
  1743      Fts5Sorter *pSorter = pCsr->pSorter;
  1744      int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
  1745      *pn = pSorter->aIdx[iPhrase] - i1;
  1746      *pa = &pSorter->aPoslist[i1];
  1747    }else{
  1748      *pn = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa);
  1749    }
  1750  
  1751    return rc;
  1752  }
  1753  
  1754  /*
  1755  ** Ensure that the Fts5Cursor.nInstCount and aInst[] variables are populated
  1756  ** correctly for the current view. Return SQLITE_OK if successful, or an
  1757  ** SQLite error code otherwise.
  1758  */
  1759  static int fts5CacheInstArray(Fts5Cursor *pCsr){
  1760    int rc = SQLITE_OK;
  1761    Fts5PoslistReader *aIter;       /* One iterator for each phrase */
  1762    int nIter;                      /* Number of iterators/phrases */
  1763    
  1764    nIter = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
  1765    if( pCsr->aInstIter==0 ){
  1766      int nByte = sizeof(Fts5PoslistReader) * nIter;
  1767      pCsr->aInstIter = (Fts5PoslistReader*)sqlite3Fts5MallocZero(&rc, nByte);
  1768    }
  1769    aIter = pCsr->aInstIter;
  1770  
  1771    if( aIter ){
  1772      int nInst = 0;                /* Number instances seen so far */
  1773      int i;
  1774  
  1775      /* Initialize all iterators */
  1776      for(i=0; i<nIter && rc==SQLITE_OK; i++){
  1777        const u8 *a;
  1778        int n; 
  1779        rc = fts5CsrPoslist(pCsr, i, &a, &n);
  1780        if( rc==SQLITE_OK ){
  1781          sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]);
  1782        }
  1783      }
  1784  
  1785      if( rc==SQLITE_OK ){
  1786        while( 1 ){
  1787          int *aInst;
  1788          int iBest = -1;
  1789          for(i=0; i<nIter; i++){
  1790            if( (aIter[i].bEof==0) 
  1791                && (iBest<0 || aIter[i].iPos<aIter[iBest].iPos) 
  1792              ){
  1793              iBest = i;
  1794            }
  1795          }
  1796          if( iBest<0 ) break;
  1797  
  1798          nInst++;
  1799          if( nInst>=pCsr->nInstAlloc ){
  1800            pCsr->nInstAlloc = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
  1801            aInst = (int*)sqlite3_realloc(
  1802                pCsr->aInst, pCsr->nInstAlloc*sizeof(int)*3
  1803                );
  1804            if( aInst ){
  1805              pCsr->aInst = aInst;
  1806            }else{
  1807              rc = SQLITE_NOMEM;
  1808              break;
  1809            }
  1810          }
  1811  
  1812          aInst = &pCsr->aInst[3 * (nInst-1)];
  1813          aInst[0] = iBest;
  1814          aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos);
  1815          aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos);
  1816          sqlite3Fts5PoslistReaderNext(&aIter[iBest]);
  1817        }
  1818      }
  1819  
  1820      pCsr->nInstCount = nInst;
  1821      CsrFlagClear(pCsr, FTS5CSR_REQUIRE_INST);
  1822    }
  1823    return rc;
  1824  }
  1825  
  1826  static int fts5ApiInstCount(Fts5Context *pCtx, int *pnInst){
  1827    Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  1828    int rc = SQLITE_OK;
  1829    if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0 
  1830     || SQLITE_OK==(rc = fts5CacheInstArray(pCsr)) ){
  1831      *pnInst = pCsr->nInstCount;
  1832    }
  1833    return rc;
  1834  }
  1835  
  1836  static int fts5ApiInst(
  1837    Fts5Context *pCtx, 
  1838    int iIdx, 
  1839    int *piPhrase, 
  1840    int *piCol, 
  1841    int *piOff
  1842  ){
  1843    Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  1844    int rc = SQLITE_OK;
  1845    if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0 
  1846     || SQLITE_OK==(rc = fts5CacheInstArray(pCsr)) 
  1847    ){
  1848      if( iIdx<0 || iIdx>=pCsr->nInstCount ){
  1849        rc = SQLITE_RANGE;
  1850  #if 0
  1851      }else if( fts5IsOffsetless((Fts5Table*)pCsr->base.pVtab) ){
  1852        *piPhrase = pCsr->aInst[iIdx*3];
  1853        *piCol = pCsr->aInst[iIdx*3 + 2];
  1854        *piOff = -1;
  1855  #endif
  1856      }else{
  1857        *piPhrase = pCsr->aInst[iIdx*3];
  1858        *piCol = pCsr->aInst[iIdx*3 + 1];
  1859        *piOff = pCsr->aInst[iIdx*3 + 2];
  1860      }
  1861    }
  1862    return rc;
  1863  }
  1864  
  1865  static sqlite3_int64 fts5ApiRowid(Fts5Context *pCtx){
  1866    return fts5CursorRowid((Fts5Cursor*)pCtx);
  1867  }
  1868  
  1869  static int fts5ColumnSizeCb(
  1870    void *pContext,                 /* Pointer to int */
  1871    int tflags,
  1872    const char *pUnused,            /* Buffer containing token */
  1873    int nUnused,                    /* Size of token in bytes */
  1874    int iUnused1,                   /* Start offset of token */
  1875    int iUnused2                    /* End offset of token */
  1876  ){
  1877    int *pCnt = (int*)pContext;
  1878    UNUSED_PARAM2(pUnused, nUnused);
  1879    UNUSED_PARAM2(iUnused1, iUnused2);
  1880    if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){
  1881      (*pCnt)++;
  1882    }
  1883    return SQLITE_OK;
  1884  }
  1885  
  1886  static int fts5ApiColumnSize(Fts5Context *pCtx, int iCol, int *pnToken){
  1887    Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  1888    Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
  1889    Fts5Config *pConfig = pTab->pConfig;
  1890    int rc = SQLITE_OK;
  1891  
  1892    if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_DOCSIZE) ){
  1893      if( pConfig->bColumnsize ){
  1894        i64 iRowid = fts5CursorRowid(pCsr);
  1895        rc = sqlite3Fts5StorageDocsize(pTab->pStorage, iRowid, pCsr->aColumnSize);
  1896      }else if( pConfig->zContent==0 ){
  1897        int i;
  1898        for(i=0; i<pConfig->nCol; i++){
  1899          if( pConfig->abUnindexed[i]==0 ){
  1900            pCsr->aColumnSize[i] = -1;
  1901          }
  1902        }
  1903      }else{
  1904        int i;
  1905        for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
  1906          if( pConfig->abUnindexed[i]==0 ){
  1907            const char *z; int n;
  1908            void *p = (void*)(&pCsr->aColumnSize[i]);
  1909            pCsr->aColumnSize[i] = 0;
  1910            rc = fts5ApiColumnText(pCtx, i, &z, &n);
  1911            if( rc==SQLITE_OK ){
  1912              rc = sqlite3Fts5Tokenize(
  1913                  pConfig, FTS5_TOKENIZE_AUX, z, n, p, fts5ColumnSizeCb
  1914              );
  1915            }
  1916          }
  1917        }
  1918      }
  1919      CsrFlagClear(pCsr, FTS5CSR_REQUIRE_DOCSIZE);
  1920    }
  1921    if( iCol<0 ){
  1922      int i;
  1923      *pnToken = 0;
  1924      for(i=0; i<pConfig->nCol; i++){
  1925        *pnToken += pCsr->aColumnSize[i];
  1926      }
  1927    }else if( iCol<pConfig->nCol ){
  1928      *pnToken = pCsr->aColumnSize[iCol];
  1929    }else{
  1930      *pnToken = 0;
  1931      rc = SQLITE_RANGE;
  1932    }
  1933    return rc;
  1934  }
  1935  
  1936  /*
  1937  ** Implementation of the xSetAuxdata() method.
  1938  */
  1939  static int fts5ApiSetAuxdata(
  1940    Fts5Context *pCtx,              /* Fts5 context */
  1941    void *pPtr,                     /* Pointer to save as auxdata */
  1942    void(*xDelete)(void*)           /* Destructor for pPtr (or NULL) */
  1943  ){
  1944    Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  1945    Fts5Auxdata *pData;
  1946  
  1947    /* Search through the cursors list of Fts5Auxdata objects for one that
  1948    ** corresponds to the currently executing auxiliary function.  */
  1949    for(pData=pCsr->pAuxdata; pData; pData=pData->pNext){
  1950      if( pData->pAux==pCsr->pAux ) break;
  1951    }
  1952  
  1953    if( pData ){
  1954      if( pData->xDelete ){
  1955        pData->xDelete(pData->pPtr);
  1956      }
  1957    }else{
  1958      int rc = SQLITE_OK;
  1959      pData = (Fts5Auxdata*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Auxdata));
  1960      if( pData==0 ){
  1961        if( xDelete ) xDelete(pPtr);
  1962        return rc;
  1963      }
  1964      pData->pAux = pCsr->pAux;
  1965      pData->pNext = pCsr->pAuxdata;
  1966      pCsr->pAuxdata = pData;
  1967    }
  1968  
  1969    pData->xDelete = xDelete;
  1970    pData->pPtr = pPtr;
  1971    return SQLITE_OK;
  1972  }
  1973  
  1974  static void *fts5ApiGetAuxdata(Fts5Context *pCtx, int bClear){
  1975    Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  1976    Fts5Auxdata *pData;
  1977    void *pRet = 0;
  1978  
  1979    for(pData=pCsr->pAuxdata; pData; pData=pData->pNext){
  1980      if( pData->pAux==pCsr->pAux ) break;
  1981    }
  1982  
  1983    if( pData ){
  1984      pRet = pData->pPtr;
  1985      if( bClear ){
  1986        pData->pPtr = 0;
  1987        pData->xDelete = 0;
  1988      }
  1989    }
  1990  
  1991    return pRet;
  1992  }
  1993  
  1994  static void fts5ApiPhraseNext(
  1995    Fts5Context *pUnused, 
  1996    Fts5PhraseIter *pIter, 
  1997    int *piCol, int *piOff
  1998  ){
  1999    UNUSED_PARAM(pUnused);
  2000    if( pIter->a>=pIter->b ){
  2001      *piCol = -1;
  2002      *piOff = -1;
  2003    }else{
  2004      int iVal;
  2005      pIter->a += fts5GetVarint32(pIter->a, iVal);
  2006      if( iVal==1 ){
  2007        pIter->a += fts5GetVarint32(pIter->a, iVal);
  2008        *piCol = iVal;
  2009        *piOff = 0;
  2010        pIter->a += fts5GetVarint32(pIter->a, iVal);
  2011      }
  2012      *piOff += (iVal-2);
  2013    }
  2014  }
  2015  
  2016  static int fts5ApiPhraseFirst(
  2017    Fts5Context *pCtx, 
  2018    int iPhrase, 
  2019    Fts5PhraseIter *pIter, 
  2020    int *piCol, int *piOff
  2021  ){
  2022    Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  2023    int n;
  2024    int rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
  2025    if( rc==SQLITE_OK ){
  2026      pIter->b = &pIter->a[n];
  2027      *piCol = 0;
  2028      *piOff = 0;
  2029      fts5ApiPhraseNext(pCtx, pIter, piCol, piOff);
  2030    }
  2031    return rc;
  2032  }
  2033  
  2034  static void fts5ApiPhraseNextColumn(
  2035    Fts5Context *pCtx, 
  2036    Fts5PhraseIter *pIter, 
  2037    int *piCol
  2038  ){
  2039    Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  2040    Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
  2041  
  2042    if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
  2043      if( pIter->a>=pIter->b ){
  2044        *piCol = -1;
  2045      }else{
  2046        int iIncr;
  2047        pIter->a += fts5GetVarint32(&pIter->a[0], iIncr);
  2048        *piCol += (iIncr-2);
  2049      }
  2050    }else{
  2051      while( 1 ){
  2052        int dummy;
  2053        if( pIter->a>=pIter->b ){
  2054          *piCol = -1;
  2055          return;
  2056        }
  2057        if( pIter->a[0]==0x01 ) break;
  2058        pIter->a += fts5GetVarint32(pIter->a, dummy);
  2059      }
  2060      pIter->a += 1 + fts5GetVarint32(&pIter->a[1], *piCol);
  2061    }
  2062  }
  2063  
  2064  static int fts5ApiPhraseFirstColumn(
  2065    Fts5Context *pCtx, 
  2066    int iPhrase, 
  2067    Fts5PhraseIter *pIter, 
  2068    int *piCol
  2069  ){
  2070    int rc = SQLITE_OK;
  2071    Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  2072    Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
  2073  
  2074    if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
  2075      Fts5Sorter *pSorter = pCsr->pSorter;
  2076      int n;
  2077      if( pSorter ){
  2078        int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
  2079        n = pSorter->aIdx[iPhrase] - i1;
  2080        pIter->a = &pSorter->aPoslist[i1];
  2081      }else{
  2082        rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, iPhrase, &pIter->a, &n);
  2083      }
  2084      if( rc==SQLITE_OK ){
  2085        pIter->b = &pIter->a[n];
  2086        *piCol = 0;
  2087        fts5ApiPhraseNextColumn(pCtx, pIter, piCol);
  2088      }
  2089    }else{
  2090      int n;
  2091      rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
  2092      if( rc==SQLITE_OK ){
  2093        pIter->b = &pIter->a[n];
  2094        if( n<=0 ){
  2095          *piCol = -1;
  2096        }else if( pIter->a[0]==0x01 ){
  2097          pIter->a += 1 + fts5GetVarint32(&pIter->a[1], *piCol);
  2098        }else{
  2099          *piCol = 0;
  2100        }
  2101      }
  2102    }
  2103  
  2104    return rc;
  2105  }
  2106  
  2107  
  2108  static int fts5ApiQueryPhrase(Fts5Context*, int, void*, 
  2109      int(*)(const Fts5ExtensionApi*, Fts5Context*, void*)
  2110  );
  2111  
  2112  static const Fts5ExtensionApi sFts5Api = {
  2113    2,                            /* iVersion */
  2114    fts5ApiUserData,
  2115    fts5ApiColumnCount,
  2116    fts5ApiRowCount,
  2117    fts5ApiColumnTotalSize,
  2118    fts5ApiTokenize,
  2119    fts5ApiPhraseCount,
  2120    fts5ApiPhraseSize,
  2121    fts5ApiInstCount,
  2122    fts5ApiInst,
  2123    fts5ApiRowid,
  2124    fts5ApiColumnText,
  2125    fts5ApiColumnSize,
  2126    fts5ApiQueryPhrase,
  2127    fts5ApiSetAuxdata,
  2128    fts5ApiGetAuxdata,
  2129    fts5ApiPhraseFirst,
  2130    fts5ApiPhraseNext,
  2131    fts5ApiPhraseFirstColumn,
  2132    fts5ApiPhraseNextColumn,
  2133  };
  2134  
  2135  /*
  2136  ** Implementation of API function xQueryPhrase().
  2137  */
  2138  static int fts5ApiQueryPhrase(
  2139    Fts5Context *pCtx, 
  2140    int iPhrase, 
  2141    void *pUserData,
  2142    int(*xCallback)(const Fts5ExtensionApi*, Fts5Context*, void*)
  2143  ){
  2144    Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  2145    Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
  2146    int rc;
  2147    Fts5Cursor *pNew = 0;
  2148  
  2149    rc = fts5OpenMethod(pCsr->base.pVtab, (sqlite3_vtab_cursor**)&pNew);
  2150    if( rc==SQLITE_OK ){
  2151      pNew->ePlan = FTS5_PLAN_MATCH;
  2152      pNew->iFirstRowid = SMALLEST_INT64;
  2153      pNew->iLastRowid = LARGEST_INT64;
  2154      pNew->base.pVtab = (sqlite3_vtab*)pTab;
  2155      rc = sqlite3Fts5ExprClonePhrase(pCsr->pExpr, iPhrase, &pNew->pExpr);
  2156    }
  2157  
  2158    if( rc==SQLITE_OK ){
  2159      for(rc = fts5CursorFirst(pTab, pNew, 0);
  2160          rc==SQLITE_OK && CsrFlagTest(pNew, FTS5CSR_EOF)==0;
  2161          rc = fts5NextMethod((sqlite3_vtab_cursor*)pNew)
  2162      ){
  2163        rc = xCallback(&sFts5Api, (Fts5Context*)pNew, pUserData);
  2164        if( rc!=SQLITE_OK ){
  2165          if( rc==SQLITE_DONE ) rc = SQLITE_OK;
  2166          break;
  2167        }
  2168      }
  2169    }
  2170  
  2171    fts5CloseMethod((sqlite3_vtab_cursor*)pNew);
  2172    return rc;
  2173  }
  2174  
  2175  static void fts5ApiInvoke(
  2176    Fts5Auxiliary *pAux,
  2177    Fts5Cursor *pCsr,
  2178    sqlite3_context *context,
  2179    int argc,
  2180    sqlite3_value **argv
  2181  ){
  2182    assert( pCsr->pAux==0 );
  2183    pCsr->pAux = pAux;
  2184    pAux->xFunc(&sFts5Api, (Fts5Context*)pCsr, context, argc, argv);
  2185    pCsr->pAux = 0;
  2186  }
  2187  
  2188  static Fts5Cursor *fts5CursorFromCsrid(Fts5Global *pGlobal, i64 iCsrId){
  2189    Fts5Cursor *pCsr;
  2190    for(pCsr=pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
  2191      if( pCsr->iCsrId==iCsrId ) break;
  2192    }
  2193    return pCsr;
  2194  }
  2195  
  2196  static void fts5ApiCallback(
  2197    sqlite3_context *context,
  2198    int argc,
  2199    sqlite3_value **argv
  2200  ){
  2201  
  2202    Fts5Auxiliary *pAux;
  2203    Fts5Cursor *pCsr;
  2204    i64 iCsrId;
  2205  
  2206    assert( argc>=1 );
  2207    pAux = (Fts5Auxiliary*)sqlite3_user_data(context);
  2208    iCsrId = sqlite3_value_int64(argv[0]);
  2209  
  2210    pCsr = fts5CursorFromCsrid(pAux->pGlobal, iCsrId);
  2211    if( pCsr==0 ){
  2212      char *zErr = sqlite3_mprintf("no such cursor: %lld", iCsrId);
  2213      sqlite3_result_error(context, zErr, -1);
  2214      sqlite3_free(zErr);
  2215    }else{
  2216      fts5ApiInvoke(pAux, pCsr, context, argc-1, &argv[1]);
  2217    }
  2218  }
  2219  
  2220  
  2221  /*
  2222  ** Given cursor id iId, return a pointer to the corresponding Fts5Index 
  2223  ** object. Or NULL If the cursor id does not exist.
  2224  **
  2225  ** If successful, set *ppConfig to point to the associated config object 
  2226  ** before returning.
  2227  */
  2228  Fts5Index *sqlite3Fts5IndexFromCsrid(
  2229    Fts5Global *pGlobal,            /* FTS5 global context for db handle */
  2230    i64 iCsrId,                     /* Id of cursor to find */
  2231    Fts5Config **ppConfig           /* OUT: Configuration object */
  2232  ){
  2233    Fts5Cursor *pCsr;
  2234    Fts5Table *pTab;
  2235  
  2236    pCsr = fts5CursorFromCsrid(pGlobal, iCsrId);
  2237    pTab = (Fts5Table*)pCsr->base.pVtab;
  2238    *ppConfig = pTab->pConfig;
  2239  
  2240    return pTab->pIndex;
  2241  }
  2242  
  2243  /*
  2244  ** Return a "position-list blob" corresponding to the current position of
  2245  ** cursor pCsr via sqlite3_result_blob(). A position-list blob contains
  2246  ** the current position-list for each phrase in the query associated with
  2247  ** cursor pCsr.
  2248  **
  2249  ** A position-list blob begins with (nPhrase-1) varints, where nPhrase is
  2250  ** the number of phrases in the query. Following the varints are the
  2251  ** concatenated position lists for each phrase, in order.
  2252  **
  2253  ** The first varint (if it exists) contains the size of the position list
  2254  ** for phrase 0. The second (same disclaimer) contains the size of position
  2255  ** list 1. And so on. There is no size field for the final position list,
  2256  ** as it can be derived from the total size of the blob.
  2257  */
  2258  static int fts5PoslistBlob(sqlite3_context *pCtx, Fts5Cursor *pCsr){
  2259    int i;
  2260    int rc = SQLITE_OK;
  2261    int nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
  2262    Fts5Buffer val;
  2263  
  2264    memset(&val, 0, sizeof(Fts5Buffer));
  2265    switch( ((Fts5Table*)(pCsr->base.pVtab))->pConfig->eDetail ){
  2266      case FTS5_DETAIL_FULL:
  2267  
  2268        /* Append the varints */
  2269        for(i=0; i<(nPhrase-1); i++){
  2270          const u8 *dummy;
  2271          int nByte = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &dummy);
  2272          sqlite3Fts5BufferAppendVarint(&rc, &val, nByte);
  2273        }
  2274  
  2275        /* Append the position lists */
  2276        for(i=0; i<nPhrase; i++){
  2277          const u8 *pPoslist;
  2278          int nPoslist;
  2279          nPoslist = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &pPoslist);
  2280          sqlite3Fts5BufferAppendBlob(&rc, &val, nPoslist, pPoslist);
  2281        }
  2282        break;
  2283  
  2284      case FTS5_DETAIL_COLUMNS:
  2285  
  2286        /* Append the varints */
  2287        for(i=0; rc==SQLITE_OK && i<(nPhrase-1); i++){
  2288          const u8 *dummy;
  2289          int nByte;
  2290          rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, i, &dummy, &nByte);
  2291          sqlite3Fts5BufferAppendVarint(&rc, &val, nByte);
  2292        }
  2293  
  2294        /* Append the position lists */
  2295        for(i=0; rc==SQLITE_OK && i<nPhrase; i++){
  2296          const u8 *pPoslist;
  2297          int nPoslist;
  2298          rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, i, &pPoslist, &nPoslist);
  2299          sqlite3Fts5BufferAppendBlob(&rc, &val, nPoslist, pPoslist);
  2300        }
  2301        break;
  2302  
  2303      default:
  2304        break;
  2305    }
  2306  
  2307    sqlite3_result_blob(pCtx, val.p, val.n, sqlite3_free);
  2308    return rc;
  2309  }
  2310  
  2311  /* 
  2312  ** This is the xColumn method, called by SQLite to request a value from
  2313  ** the row that the supplied cursor currently points to.
  2314  */
  2315  static int fts5ColumnMethod(
  2316    sqlite3_vtab_cursor *pCursor,   /* Cursor to retrieve value from */
  2317    sqlite3_context *pCtx,          /* Context for sqlite3_result_xxx() calls */
  2318    int iCol                        /* Index of column to read value from */
  2319  ){
  2320    Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
  2321    Fts5Config *pConfig = pTab->pConfig;
  2322    Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
  2323    int rc = SQLITE_OK;
  2324    
  2325    assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 );
  2326  
  2327    if( pCsr->ePlan==FTS5_PLAN_SPECIAL ){
  2328      if( iCol==pConfig->nCol ){
  2329        sqlite3_result_int64(pCtx, pCsr->iSpecial);
  2330      }
  2331    }else
  2332  
  2333    if( iCol==pConfig->nCol ){
  2334      /* User is requesting the value of the special column with the same name
  2335      ** as the table. Return the cursor integer id number. This value is only
  2336      ** useful in that it may be passed as the first argument to an FTS5
  2337      ** auxiliary function.  */
  2338      sqlite3_result_int64(pCtx, pCsr->iCsrId);
  2339    }else if( iCol==pConfig->nCol+1 ){
  2340  
  2341      /* The value of the "rank" column. */
  2342      if( pCsr->ePlan==FTS5_PLAN_SOURCE ){
  2343        fts5PoslistBlob(pCtx, pCsr);
  2344      }else if( 
  2345          pCsr->ePlan==FTS5_PLAN_MATCH
  2346       || pCsr->ePlan==FTS5_PLAN_SORTED_MATCH
  2347      ){
  2348        if( pCsr->pRank || SQLITE_OK==(rc = fts5FindRankFunction(pCsr)) ){
  2349          fts5ApiInvoke(pCsr->pRank, pCsr, pCtx, pCsr->nRankArg, pCsr->apRankArg);
  2350        }
  2351      }
  2352    }else if( !fts5IsContentless(pTab) ){
  2353      rc = fts5SeekCursor(pCsr, 1);
  2354      if( rc==SQLITE_OK ){
  2355        sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
  2356      }
  2357    }
  2358    return rc;
  2359  }
  2360  
  2361  
  2362  /*
  2363  ** This routine implements the xFindFunction method for the FTS3
  2364  ** virtual table.
  2365  */
  2366  static int fts5FindFunctionMethod(
  2367    sqlite3_vtab *pVtab,            /* Virtual table handle */
  2368    int nUnused,                    /* Number of SQL function arguments */
  2369    const char *zName,              /* Name of SQL function */
  2370    void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
  2371    void **ppArg                    /* OUT: User data for *pxFunc */
  2372  ){
  2373    Fts5Table *pTab = (Fts5Table*)pVtab;
  2374    Fts5Auxiliary *pAux;
  2375  
  2376    UNUSED_PARAM(nUnused);
  2377    pAux = fts5FindAuxiliary(pTab, zName);
  2378    if( pAux ){
  2379      *pxFunc = fts5ApiCallback;
  2380      *ppArg = (void*)pAux;
  2381      return 1;
  2382    }
  2383  
  2384    /* No function of the specified name was found. Return 0. */
  2385    return 0;
  2386  }
  2387  
  2388  /*
  2389  ** Implementation of FTS5 xRename method. Rename an fts5 table.
  2390  */
  2391  static int fts5RenameMethod(
  2392    sqlite3_vtab *pVtab,            /* Virtual table handle */
  2393    const char *zName               /* New name of table */
  2394  ){
  2395    Fts5Table *pTab = (Fts5Table*)pVtab;
  2396    return sqlite3Fts5StorageRename(pTab->pStorage, zName);
  2397  }
  2398  
  2399  /*
  2400  ** The xSavepoint() method.
  2401  **
  2402  ** Flush the contents of the pending-terms table to disk.
  2403  */
  2404  static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
  2405    Fts5Table *pTab = (Fts5Table*)pVtab;
  2406    UNUSED_PARAM(iSavepoint);  /* Call below is a no-op for NDEBUG builds */
  2407    fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint);
  2408    fts5TripCursors(pTab);
  2409    return sqlite3Fts5StorageSync(pTab->pStorage);
  2410  }
  2411  
  2412  /*
  2413  ** The xRelease() method.
  2414  **
  2415  ** This is a no-op.
  2416  */
  2417  static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
  2418    Fts5Table *pTab = (Fts5Table*)pVtab;
  2419    UNUSED_PARAM(iSavepoint);  /* Call below is a no-op for NDEBUG builds */
  2420    fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint);
  2421    fts5TripCursors(pTab);
  2422    return sqlite3Fts5StorageSync(pTab->pStorage);
  2423  }
  2424  
  2425  /*
  2426  ** The xRollbackTo() method.
  2427  **
  2428  ** Discard the contents of the pending terms table.
  2429  */
  2430  static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
  2431    Fts5Table *pTab = (Fts5Table*)pVtab;
  2432    UNUSED_PARAM(iSavepoint);  /* Call below is a no-op for NDEBUG builds */
  2433    fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint);
  2434    fts5TripCursors(pTab);
  2435    return sqlite3Fts5StorageRollback(pTab->pStorage);
  2436  }
  2437  
  2438  /*
  2439  ** Register a new auxiliary function with global context pGlobal.
  2440  */
  2441  static int fts5CreateAux(
  2442    fts5_api *pApi,                 /* Global context (one per db handle) */
  2443    const char *zName,              /* Name of new function */
  2444    void *pUserData,                /* User data for aux. function */
  2445    fts5_extension_function xFunc,  /* Aux. function implementation */
  2446    void(*xDestroy)(void*)          /* Destructor for pUserData */
  2447  ){
  2448    Fts5Global *pGlobal = (Fts5Global*)pApi;
  2449    int rc = sqlite3_overload_function(pGlobal->db, zName, -1);
  2450    if( rc==SQLITE_OK ){
  2451      Fts5Auxiliary *pAux;
  2452      int nName;                      /* Size of zName in bytes, including \0 */
  2453      int nByte;                      /* Bytes of space to allocate */
  2454  
  2455      nName = (int)strlen(zName) + 1;
  2456      nByte = sizeof(Fts5Auxiliary) + nName;
  2457      pAux = (Fts5Auxiliary*)sqlite3_malloc(nByte);
  2458      if( pAux ){
  2459        memset(pAux, 0, nByte);
  2460        pAux->zFunc = (char*)&pAux[1];
  2461        memcpy(pAux->zFunc, zName, nName);
  2462        pAux->pGlobal = pGlobal;
  2463        pAux->pUserData = pUserData;
  2464        pAux->xFunc = xFunc;
  2465        pAux->xDestroy = xDestroy;
  2466        pAux->pNext = pGlobal->pAux;
  2467        pGlobal->pAux = pAux;
  2468      }else{
  2469        rc = SQLITE_NOMEM;
  2470      }
  2471    }
  2472  
  2473    return rc;
  2474  }
  2475  
  2476  /*
  2477  ** Register a new tokenizer. This is the implementation of the 
  2478  ** fts5_api.xCreateTokenizer() method.
  2479  */
  2480  static int fts5CreateTokenizer(
  2481    fts5_api *pApi,                 /* Global context (one per db handle) */
  2482    const char *zName,              /* Name of new function */
  2483    void *pUserData,                /* User data for aux. function */
  2484    fts5_tokenizer *pTokenizer,     /* Tokenizer implementation */
  2485    void(*xDestroy)(void*)          /* Destructor for pUserData */
  2486  ){
  2487    Fts5Global *pGlobal = (Fts5Global*)pApi;
  2488    Fts5TokenizerModule *pNew;
  2489    int nName;                      /* Size of zName and its \0 terminator */
  2490    int nByte;                      /* Bytes of space to allocate */
  2491    int rc = SQLITE_OK;
  2492  
  2493    nName = (int)strlen(zName) + 1;
  2494    nByte = sizeof(Fts5TokenizerModule) + nName;
  2495    pNew = (Fts5TokenizerModule*)sqlite3_malloc(nByte);
  2496    if( pNew ){
  2497      memset(pNew, 0, nByte);
  2498      pNew->zName = (char*)&pNew[1];
  2499      memcpy(pNew->zName, zName, nName);
  2500      pNew->pUserData = pUserData;
  2501      pNew->x = *pTokenizer;
  2502      pNew->xDestroy = xDestroy;
  2503      pNew->pNext = pGlobal->pTok;
  2504      pGlobal->pTok = pNew;
  2505      if( pNew->pNext==0 ){
  2506        pGlobal->pDfltTok = pNew;
  2507      }
  2508    }else{
  2509      rc = SQLITE_NOMEM;
  2510    }
  2511  
  2512    return rc;
  2513  }
  2514  
  2515  static Fts5TokenizerModule *fts5LocateTokenizer(
  2516    Fts5Global *pGlobal, 
  2517    const char *zName
  2518  ){
  2519    Fts5TokenizerModule *pMod = 0;
  2520  
  2521    if( zName==0 ){
  2522      pMod = pGlobal->pDfltTok;
  2523    }else{
  2524      for(pMod=pGlobal->pTok; pMod; pMod=pMod->pNext){
  2525        if( sqlite3_stricmp(zName, pMod->zName)==0 ) break;
  2526      }
  2527    }
  2528  
  2529    return pMod;
  2530  }
  2531  
  2532  /*
  2533  ** Find a tokenizer. This is the implementation of the 
  2534  ** fts5_api.xFindTokenizer() method.
  2535  */
  2536  static int fts5FindTokenizer(
  2537    fts5_api *pApi,                 /* Global context (one per db handle) */
  2538    const char *zName,              /* Name of new function */
  2539    void **ppUserData,
  2540    fts5_tokenizer *pTokenizer      /* Populate this object */
  2541  ){
  2542    int rc = SQLITE_OK;
  2543    Fts5TokenizerModule *pMod;
  2544  
  2545    pMod = fts5LocateTokenizer((Fts5Global*)pApi, zName);
  2546    if( pMod ){
  2547      *pTokenizer = pMod->x;
  2548      *ppUserData = pMod->pUserData;
  2549    }else{
  2550      memset(pTokenizer, 0, sizeof(fts5_tokenizer));
  2551      rc = SQLITE_ERROR;
  2552    }
  2553  
  2554    return rc;
  2555  }
  2556  
  2557  int sqlite3Fts5GetTokenizer(
  2558    Fts5Global *pGlobal, 
  2559    const char **azArg,
  2560    int nArg,
  2561    Fts5Tokenizer **ppTok,
  2562    fts5_tokenizer **ppTokApi,
  2563    char **pzErr
  2564  ){
  2565    Fts5TokenizerModule *pMod;
  2566    int rc = SQLITE_OK;
  2567  
  2568    pMod = fts5LocateTokenizer(pGlobal, nArg==0 ? 0 : azArg[0]);
  2569    if( pMod==0 ){
  2570      assert( nArg>0 );
  2571      rc = SQLITE_ERROR;
  2572      *pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
  2573    }else{
  2574      rc = pMod->x.xCreate(pMod->pUserData, &azArg[1], (nArg?nArg-1:0), ppTok);
  2575      *ppTokApi = &pMod->x;
  2576      if( rc!=SQLITE_OK && pzErr ){
  2577        *pzErr = sqlite3_mprintf("error in tokenizer constructor");
  2578      }
  2579    }
  2580  
  2581    if( rc!=SQLITE_OK ){
  2582      *ppTokApi = 0;
  2583      *ppTok = 0;
  2584    }
  2585  
  2586    return rc;
  2587  }
  2588  
  2589  static void fts5ModuleDestroy(void *pCtx){
  2590    Fts5TokenizerModule *pTok, *pNextTok;
  2591    Fts5Auxiliary *pAux, *pNextAux;
  2592    Fts5Global *pGlobal = (Fts5Global*)pCtx;
  2593  
  2594    for(pAux=pGlobal->pAux; pAux; pAux=pNextAux){
  2595      pNextAux = pAux->pNext;
  2596      if( pAux->xDestroy ) pAux->xDestroy(pAux->pUserData);
  2597      sqlite3_free(pAux);
  2598    }
  2599  
  2600    for(pTok=pGlobal->pTok; pTok; pTok=pNextTok){
  2601      pNextTok = pTok->pNext;
  2602      if( pTok->xDestroy ) pTok->xDestroy(pTok->pUserData);
  2603      sqlite3_free(pTok);
  2604    }
  2605  
  2606    sqlite3_free(pGlobal);
  2607  }
  2608  
  2609  static void fts5Fts5Func(
  2610    sqlite3_context *pCtx,          /* Function call context */
  2611    int nArg,                       /* Number of args */
  2612    sqlite3_value **apArg           /* Function arguments */
  2613  ){
  2614    Fts5Global *pGlobal = (Fts5Global*)sqlite3_user_data(pCtx);
  2615    fts5_api **ppApi;
  2616    UNUSED_PARAM(nArg);
  2617    assert( nArg==1 );
  2618    ppApi = (fts5_api**)sqlite3_value_pointer(apArg[0], "fts5_api_ptr");
  2619    if( ppApi ) *ppApi = &pGlobal->api;
  2620  }
  2621  
  2622  /*
  2623  ** Implementation of fts5_source_id() function.
  2624  */
  2625  static void fts5SourceIdFunc(
  2626    sqlite3_context *pCtx,          /* Function call context */
  2627    int nArg,                       /* Number of args */
  2628    sqlite3_value **apUnused        /* Function arguments */
  2629  ){
  2630    assert( nArg==0 );
  2631    UNUSED_PARAM2(nArg, apUnused);
  2632    sqlite3_result_text(pCtx, "--FTS5-SOURCE-ID--", -1, SQLITE_TRANSIENT);
  2633  }
  2634  
  2635  static int fts5Init(sqlite3 *db){
  2636    static const sqlite3_module fts5Mod = {
  2637      /* iVersion      */ 2,
  2638      /* xCreate       */ fts5CreateMethod,
  2639      /* xConnect      */ fts5ConnectMethod,
  2640      /* xBestIndex    */ fts5BestIndexMethod,
  2641      /* xDisconnect   */ fts5DisconnectMethod,
  2642      /* xDestroy      */ fts5DestroyMethod,
  2643      /* xOpen         */ fts5OpenMethod,
  2644      /* xClose        */ fts5CloseMethod,
  2645      /* xFilter       */ fts5FilterMethod,
  2646      /* xNext         */ fts5NextMethod,
  2647      /* xEof          */ fts5EofMethod,
  2648      /* xColumn       */ fts5ColumnMethod,
  2649      /* xRowid        */ fts5RowidMethod,
  2650      /* xUpdate       */ fts5UpdateMethod,
  2651      /* xBegin        */ fts5BeginMethod,
  2652      /* xSync         */ fts5SyncMethod,
  2653      /* xCommit       */ fts5CommitMethod,
  2654      /* xRollback     */ fts5RollbackMethod,
  2655      /* xFindFunction */ fts5FindFunctionMethod,
  2656      /* xRename       */ fts5RenameMethod,
  2657      /* xSavepoint    */ fts5SavepointMethod,
  2658      /* xRelease      */ fts5ReleaseMethod,
  2659      /* xRollbackTo   */ fts5RollbackToMethod,
  2660    };
  2661  
  2662    int rc;
  2663    Fts5Global *pGlobal = 0;
  2664  
  2665    pGlobal = (Fts5Global*)sqlite3_malloc(sizeof(Fts5Global));
  2666    if( pGlobal==0 ){
  2667      rc = SQLITE_NOMEM;
  2668    }else{
  2669      void *p = (void*)pGlobal;
  2670      memset(pGlobal, 0, sizeof(Fts5Global));
  2671      pGlobal->db = db;
  2672      pGlobal->api.iVersion = 2;
  2673      pGlobal->api.xCreateFunction = fts5CreateAux;
  2674      pGlobal->api.xCreateTokenizer = fts5CreateTokenizer;
  2675      pGlobal->api.xFindTokenizer = fts5FindTokenizer;
  2676      rc = sqlite3_create_module_v2(db, "fts5", &fts5Mod, p, fts5ModuleDestroy);
  2677      if( rc==SQLITE_OK ) rc = sqlite3Fts5IndexInit(db);
  2678      if( rc==SQLITE_OK ) rc = sqlite3Fts5ExprInit(pGlobal, db);
  2679      if( rc==SQLITE_OK ) rc = sqlite3Fts5AuxInit(&pGlobal->api);
  2680      if( rc==SQLITE_OK ) rc = sqlite3Fts5TokenizerInit(&pGlobal->api);
  2681      if( rc==SQLITE_OK ) rc = sqlite3Fts5VocabInit(pGlobal, db);
  2682      if( rc==SQLITE_OK ){
  2683        rc = sqlite3_create_function(
  2684            db, "fts5", 1, SQLITE_UTF8, p, fts5Fts5Func, 0, 0
  2685        );
  2686      }
  2687      if( rc==SQLITE_OK ){
  2688        rc = sqlite3_create_function(
  2689            db, "fts5_source_id", 0, SQLITE_UTF8, p, fts5SourceIdFunc, 0, 0
  2690        );
  2691      }
  2692    }
  2693  
  2694    /* If SQLITE_FTS5_ENABLE_TEST_MI is defined, assume that the file
  2695    ** fts5_test_mi.c is compiled and linked into the executable. And call
  2696    ** its entry point to enable the matchinfo() demo.  */
  2697  #ifdef SQLITE_FTS5_ENABLE_TEST_MI
  2698    if( rc==SQLITE_OK ){
  2699      extern int sqlite3Fts5TestRegisterMatchinfo(sqlite3*);
  2700      rc = sqlite3Fts5TestRegisterMatchinfo(db);
  2701    }
  2702  #endif
  2703  
  2704    return rc;
  2705  }
  2706  
  2707  /*
  2708  ** The following functions are used to register the module with SQLite. If
  2709  ** this module is being built as part of the SQLite core (SQLITE_CORE is
  2710  ** defined), then sqlite3_open() will call sqlite3Fts5Init() directly.
  2711  **
  2712  ** Or, if this module is being built as a loadable extension, 
  2713  ** sqlite3Fts5Init() is omitted and the two standard entry points
  2714  ** sqlite3_fts_init() and sqlite3_fts5_init() defined instead.
  2715  */
  2716  #ifndef SQLITE_CORE
  2717  #ifdef _WIN32
  2718  __declspec(dllexport)
  2719  #endif
  2720  int sqlite3_fts_init(
  2721    sqlite3 *db,
  2722    char **pzErrMsg,
  2723    const sqlite3_api_routines *pApi
  2724  ){
  2725    SQLITE_EXTENSION_INIT2(pApi);
  2726    (void)pzErrMsg;  /* Unused parameter */
  2727    return fts5Init(db);
  2728  }
  2729  
  2730  #ifdef _WIN32
  2731  __declspec(dllexport)
  2732  #endif
  2733  int sqlite3_fts5_init(
  2734    sqlite3 *db,
  2735    char **pzErrMsg,
  2736    const sqlite3_api_routines *pApi
  2737  ){
  2738    SQLITE_EXTENSION_INIT2(pApi);
  2739    (void)pzErrMsg;  /* Unused parameter */
  2740    return fts5Init(db);
  2741  }
  2742  #else
  2743  int sqlite3Fts5Init(sqlite3 *db){
  2744    return fts5Init(db);
  2745  }
  2746  #endif