fts5_storage.c 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518
  1. /*
  2. ** 2014 May 31
  3. **
  4. ** The author disclaims copyright to this source code. In place of
  5. ** a legal notice, here is a blessing:
  6. **
  7. ** May you do good and not evil.
  8. ** May you find forgiveness for yourself and forgive others.
  9. ** May you share freely, never taking more than you give.
  10. **
  11. ******************************************************************************
  12. **
  13. */
  14. #include "fts5Int.h"
  15. /*
  16. ** pSavedRow:
  17. ** SQL statement FTS5_STMT_LOOKUP2 is a copy of FTS5_STMT_LOOKUP, it
  18. ** does a by-rowid lookup to retrieve a single row from the %_content
  19. ** table or equivalent external-content table/view.
  20. **
  21. ** However, FTS5_STMT_LOOKUP2 is only used when retrieving the original
  22. ** values for a row being UPDATEd. In that case, the SQL statement is
  23. ** not reset and pSavedRow is set to point at it. This is so that the
  24. ** insert operation that follows the delete may access the original
  25. ** row values for any new values for which sqlite3_value_nochange() returns
  26. ** true. i.e. if the user executes:
  27. **
  28. ** CREATE VIRTUAL TABLE ft USING fts5(a, b, c, locale=1);
  29. ** ...
  30. ** UPDATE fts SET a=?, b=? WHERE rowid=?;
  31. **
  32. ** then the value passed to the xUpdate() method of this table as the
  33. ** new.c value is an sqlite3_value_nochange() value. So in this case it
  34. ** must be read from the saved row stored in Fts5Storage.pSavedRow.
  35. **
  36. ** This is necessary - using sqlite3_value_nochange() instead of just having
  37. ** SQLite pass the original value back via xUpdate() - so as not to discard
  38. ** any locale information associated with such values.
  39. **
  40. */
  41. struct Fts5Storage {
  42. Fts5Config *pConfig;
  43. Fts5Index *pIndex;
  44. int bTotalsValid; /* True if nTotalRow/aTotalSize[] are valid */
  45. i64 nTotalRow; /* Total number of rows in FTS table */
  46. i64 *aTotalSize; /* Total sizes of each column */
  47. sqlite3_stmt *pSavedRow;
  48. sqlite3_stmt *aStmt[12];
  49. };
  50. #if FTS5_STMT_SCAN_ASC!=0
  51. # error "FTS5_STMT_SCAN_ASC mismatch"
  52. #endif
  53. #if FTS5_STMT_SCAN_DESC!=1
  54. # error "FTS5_STMT_SCAN_DESC mismatch"
  55. #endif
  56. #if FTS5_STMT_LOOKUP!=2
  57. # error "FTS5_STMT_LOOKUP mismatch"
  58. #endif
  59. #define FTS5_STMT_LOOKUP2 3
  60. #define FTS5_STMT_INSERT_CONTENT 4
  61. #define FTS5_STMT_REPLACE_CONTENT 5
  62. #define FTS5_STMT_DELETE_CONTENT 6
  63. #define FTS5_STMT_REPLACE_DOCSIZE 7
  64. #define FTS5_STMT_DELETE_DOCSIZE 8
  65. #define FTS5_STMT_LOOKUP_DOCSIZE 9
  66. #define FTS5_STMT_REPLACE_CONFIG 10
  67. #define FTS5_STMT_SCAN 11
  68. /*
  69. ** Prepare the two insert statements - Fts5Storage.pInsertContent and
  70. ** Fts5Storage.pInsertDocsize - if they have not already been prepared.
  71. ** Return SQLITE_OK if successful, or an SQLite error code if an error
  72. ** occurs.
  73. */
  74. static int fts5StorageGetStmt(
  75. Fts5Storage *p, /* Storage handle */
  76. int eStmt, /* FTS5_STMT_XXX constant */
  77. sqlite3_stmt **ppStmt, /* OUT: Prepared statement handle */
  78. char **pzErrMsg /* OUT: Error message (if any) */
  79. ){
  80. int rc = SQLITE_OK;
  81. /* If there is no %_docsize table, there should be no requests for
  82. ** statements to operate on it. */
  83. assert( p->pConfig->bColumnsize || (
  84. eStmt!=FTS5_STMT_REPLACE_DOCSIZE
  85. && eStmt!=FTS5_STMT_DELETE_DOCSIZE
  86. && eStmt!=FTS5_STMT_LOOKUP_DOCSIZE
  87. ));
  88. assert( eStmt>=0 && eStmt<ArraySize(p->aStmt) );
  89. if( p->aStmt[eStmt]==0 ){
  90. const char *azStmt[] = {
  91. "SELECT %s FROM %s T WHERE T.%Q >= ? AND T.%Q <= ? ORDER BY T.%Q ASC",
  92. "SELECT %s FROM %s T WHERE T.%Q <= ? AND T.%Q >= ? ORDER BY T.%Q DESC",
  93. "SELECT %s FROM %s T WHERE T.%Q=?", /* LOOKUP */
  94. "SELECT %s FROM %s T WHERE T.%Q=?", /* LOOKUP2 */
  95. "INSERT INTO %Q.'%q_content' VALUES(%s)", /* INSERT_CONTENT */
  96. "REPLACE INTO %Q.'%q_content' VALUES(%s)", /* REPLACE_CONTENT */
  97. "DELETE FROM %Q.'%q_content' WHERE id=?", /* DELETE_CONTENT */
  98. "REPLACE INTO %Q.'%q_docsize' VALUES(?,?%s)", /* REPLACE_DOCSIZE */
  99. "DELETE FROM %Q.'%q_docsize' WHERE id=?", /* DELETE_DOCSIZE */
  100. "SELECT sz%s FROM %Q.'%q_docsize' WHERE id=?", /* LOOKUP_DOCSIZE */
  101. "REPLACE INTO %Q.'%q_config' VALUES(?,?)", /* REPLACE_CONFIG */
  102. "SELECT %s FROM %s AS T", /* SCAN */
  103. };
  104. Fts5Config *pC = p->pConfig;
  105. char *zSql = 0;
  106. assert( ArraySize(azStmt)==ArraySize(p->aStmt) );
  107. switch( eStmt ){
  108. case FTS5_STMT_SCAN:
  109. zSql = sqlite3_mprintf(azStmt[eStmt],
  110. pC->zContentExprlist, pC->zContent
  111. );
  112. break;
  113. case FTS5_STMT_SCAN_ASC:
  114. case FTS5_STMT_SCAN_DESC:
  115. zSql = sqlite3_mprintf(azStmt[eStmt], pC->zContentExprlist,
  116. pC->zContent, pC->zContentRowid, pC->zContentRowid,
  117. pC->zContentRowid
  118. );
  119. break;
  120. case FTS5_STMT_LOOKUP:
  121. case FTS5_STMT_LOOKUP2:
  122. zSql = sqlite3_mprintf(azStmt[eStmt],
  123. pC->zContentExprlist, pC->zContent, pC->zContentRowid
  124. );
  125. break;
  126. case FTS5_STMT_INSERT_CONTENT:
  127. case FTS5_STMT_REPLACE_CONTENT: {
  128. char *zBind = 0;
  129. int i;
  130. assert( pC->eContent==FTS5_CONTENT_NORMAL
  131. || pC->eContent==FTS5_CONTENT_UNINDEXED
  132. );
  133. /* Add bindings for the "c*" columns - those that store the actual
  134. ** table content. If eContent==NORMAL, then there is one binding
  135. ** for each column. Or, if eContent==UNINDEXED, then there are only
  136. ** bindings for the UNINDEXED columns. */
  137. for(i=0; rc==SQLITE_OK && i<(pC->nCol+1); i++){
  138. if( !i || pC->eContent==FTS5_CONTENT_NORMAL || pC->abUnindexed[i-1] ){
  139. zBind = sqlite3Fts5Mprintf(&rc, "%z%s?%d", zBind, zBind?",":"",i+1);
  140. }
  141. }
  142. /* Add bindings for any "l*" columns. Only non-UNINDEXED columns
  143. ** require these. */
  144. if( pC->bLocale && pC->eContent==FTS5_CONTENT_NORMAL ){
  145. for(i=0; rc==SQLITE_OK && i<pC->nCol; i++){
  146. if( pC->abUnindexed[i]==0 ){
  147. zBind = sqlite3Fts5Mprintf(&rc, "%z,?%d", zBind, pC->nCol+i+2);
  148. }
  149. }
  150. }
  151. zSql = sqlite3Fts5Mprintf(&rc, azStmt[eStmt], pC->zDb, pC->zName,zBind);
  152. sqlite3_free(zBind);
  153. break;
  154. }
  155. case FTS5_STMT_REPLACE_DOCSIZE:
  156. zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName,
  157. (pC->bContentlessDelete ? ",?" : "")
  158. );
  159. break;
  160. case FTS5_STMT_LOOKUP_DOCSIZE:
  161. zSql = sqlite3_mprintf(azStmt[eStmt],
  162. (pC->bContentlessDelete ? ",origin" : ""),
  163. pC->zDb, pC->zName
  164. );
  165. break;
  166. default:
  167. zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName);
  168. break;
  169. }
  170. if( zSql==0 ){
  171. rc = SQLITE_NOMEM;
  172. }else{
  173. int f = SQLITE_PREPARE_PERSISTENT;
  174. if( eStmt>FTS5_STMT_LOOKUP2 ) f |= SQLITE_PREPARE_NO_VTAB;
  175. p->pConfig->bLock++;
  176. rc = sqlite3_prepare_v3(pC->db, zSql, -1, f, &p->aStmt[eStmt], 0);
  177. p->pConfig->bLock--;
  178. sqlite3_free(zSql);
  179. if( rc!=SQLITE_OK && pzErrMsg ){
  180. *pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));
  181. }
  182. if( rc==SQLITE_ERROR && eStmt>FTS5_STMT_LOOKUP2 && eStmt<FTS5_STMT_SCAN ){
  183. /* One of the internal tables - not the %_content table - is missing.
  184. ** This counts as a corrupted table. */
  185. rc = SQLITE_CORRUPT;
  186. }
  187. }
  188. }
  189. *ppStmt = p->aStmt[eStmt];
  190. sqlite3_reset(*ppStmt);
  191. return rc;
  192. }
  193. static int fts5ExecPrintf(
  194. sqlite3 *db,
  195. char **pzErr,
  196. const char *zFormat,
  197. ...
  198. ){
  199. int rc;
  200. va_list ap; /* ... printf arguments */
  201. char *zSql;
  202. va_start(ap, zFormat);
  203. zSql = sqlite3_vmprintf(zFormat, ap);
  204. if( zSql==0 ){
  205. rc = SQLITE_NOMEM;
  206. }else{
  207. rc = sqlite3_exec(db, zSql, 0, 0, pzErr);
  208. sqlite3_free(zSql);
  209. }
  210. va_end(ap);
  211. return rc;
  212. }
  213. /*
  214. ** Drop all shadow tables. Return SQLITE_OK if successful or an SQLite error
  215. ** code otherwise.
  216. */
  217. int sqlite3Fts5DropAll(Fts5Config *pConfig){
  218. int rc = fts5ExecPrintf(pConfig->db, 0,
  219. "DROP TABLE IF EXISTS %Q.'%q_data';"
  220. "DROP TABLE IF EXISTS %Q.'%q_idx';"
  221. "DROP TABLE IF EXISTS %Q.'%q_config';",
  222. pConfig->zDb, pConfig->zName,
  223. pConfig->zDb, pConfig->zName,
  224. pConfig->zDb, pConfig->zName
  225. );
  226. if( rc==SQLITE_OK && pConfig->bColumnsize ){
  227. rc = fts5ExecPrintf(pConfig->db, 0,
  228. "DROP TABLE IF EXISTS %Q.'%q_docsize';",
  229. pConfig->zDb, pConfig->zName
  230. );
  231. }
  232. if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
  233. rc = fts5ExecPrintf(pConfig->db, 0,
  234. "DROP TABLE IF EXISTS %Q.'%q_content';",
  235. pConfig->zDb, pConfig->zName
  236. );
  237. }
  238. return rc;
  239. }
  240. static void fts5StorageRenameOne(
  241. Fts5Config *pConfig, /* Current FTS5 configuration */
  242. int *pRc, /* IN/OUT: Error code */
  243. const char *zTail, /* Tail of table name e.g. "data", "config" */
  244. const char *zName /* New name of FTS5 table */
  245. ){
  246. if( *pRc==SQLITE_OK ){
  247. *pRc = fts5ExecPrintf(pConfig->db, 0,
  248. "ALTER TABLE %Q.'%q_%s' RENAME TO '%q_%s';",
  249. pConfig->zDb, pConfig->zName, zTail, zName, zTail
  250. );
  251. }
  252. }
  253. int sqlite3Fts5StorageRename(Fts5Storage *pStorage, const char *zName){
  254. Fts5Config *pConfig = pStorage->pConfig;
  255. int rc = sqlite3Fts5StorageSync(pStorage);
  256. fts5StorageRenameOne(pConfig, &rc, "data", zName);
  257. fts5StorageRenameOne(pConfig, &rc, "idx", zName);
  258. fts5StorageRenameOne(pConfig, &rc, "config", zName);
  259. if( pConfig->bColumnsize ){
  260. fts5StorageRenameOne(pConfig, &rc, "docsize", zName);
  261. }
  262. if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
  263. fts5StorageRenameOne(pConfig, &rc, "content", zName);
  264. }
  265. return rc;
  266. }
  267. /*
  268. ** Create the shadow table named zPost, with definition zDefn. Return
  269. ** SQLITE_OK if successful, or an SQLite error code otherwise.
  270. */
  271. int sqlite3Fts5CreateTable(
  272. Fts5Config *pConfig, /* FTS5 configuration */
  273. const char *zPost, /* Shadow table to create (e.g. "content") */
  274. const char *zDefn, /* Columns etc. for shadow table */
  275. int bWithout, /* True for without rowid */
  276. char **pzErr /* OUT: Error message */
  277. ){
  278. int rc;
  279. char *zErr = 0;
  280. rc = fts5ExecPrintf(pConfig->db, &zErr, "CREATE TABLE %Q.'%q_%q'(%s)%s",
  281. pConfig->zDb, pConfig->zName, zPost, zDefn,
  282. #ifndef SQLITE_FTS5_NO_WITHOUT_ROWID
  283. bWithout?" WITHOUT ROWID":
  284. #endif
  285. ""
  286. );
  287. if( zErr ){
  288. *pzErr = sqlite3_mprintf(
  289. "fts5: error creating shadow table %q_%s: %s",
  290. pConfig->zName, zPost, zErr
  291. );
  292. sqlite3_free(zErr);
  293. }
  294. return rc;
  295. }
  296. /*
  297. ** Open a new Fts5Index handle. If the bCreate argument is true, create
  298. ** and initialize the underlying tables
  299. **
  300. ** If successful, set *pp to point to the new object and return SQLITE_OK.
  301. ** Otherwise, set *pp to NULL and return an SQLite error code.
  302. */
  303. int sqlite3Fts5StorageOpen(
  304. Fts5Config *pConfig,
  305. Fts5Index *pIndex,
  306. int bCreate,
  307. Fts5Storage **pp,
  308. char **pzErr /* OUT: Error message */
  309. ){
  310. int rc = SQLITE_OK;
  311. Fts5Storage *p; /* New object */
  312. sqlite3_int64 nByte; /* Bytes of space to allocate */
  313. nByte = sizeof(Fts5Storage) /* Fts5Storage object */
  314. + pConfig->nCol * sizeof(i64); /* Fts5Storage.aTotalSize[] */
  315. *pp = p = (Fts5Storage*)sqlite3_malloc64(nByte);
  316. if( !p ) return SQLITE_NOMEM;
  317. memset(p, 0, (size_t)nByte);
  318. p->aTotalSize = (i64*)&p[1];
  319. p->pConfig = pConfig;
  320. p->pIndex = pIndex;
  321. if( bCreate ){
  322. if( pConfig->eContent==FTS5_CONTENT_NORMAL
  323. || pConfig->eContent==FTS5_CONTENT_UNINDEXED
  324. ){
  325. int nDefn = 32 + pConfig->nCol*10;
  326. char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 20);
  327. if( zDefn==0 ){
  328. rc = SQLITE_NOMEM;
  329. }else{
  330. int i;
  331. int iOff;
  332. sqlite3_snprintf(nDefn, zDefn, "id INTEGER PRIMARY KEY");
  333. iOff = (int)strlen(zDefn);
  334. for(i=0; i<pConfig->nCol; i++){
  335. if( pConfig->eContent==FTS5_CONTENT_NORMAL
  336. || pConfig->abUnindexed[i]
  337. ){
  338. sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i);
  339. iOff += (int)strlen(&zDefn[iOff]);
  340. }
  341. }
  342. if( pConfig->bLocale ){
  343. for(i=0; i<pConfig->nCol; i++){
  344. if( pConfig->abUnindexed[i]==0 ){
  345. sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", l%d", i);
  346. iOff += (int)strlen(&zDefn[iOff]);
  347. }
  348. }
  349. }
  350. rc = sqlite3Fts5CreateTable(pConfig, "content", zDefn, 0, pzErr);
  351. }
  352. sqlite3_free(zDefn);
  353. }
  354. if( rc==SQLITE_OK && pConfig->bColumnsize ){
  355. const char *zCols = "id INTEGER PRIMARY KEY, sz BLOB";
  356. if( pConfig->bContentlessDelete ){
  357. zCols = "id INTEGER PRIMARY KEY, sz BLOB, origin INTEGER";
  358. }
  359. rc = sqlite3Fts5CreateTable(pConfig, "docsize", zCols, 0, pzErr);
  360. }
  361. if( rc==SQLITE_OK ){
  362. rc = sqlite3Fts5CreateTable(
  363. pConfig, "config", "k PRIMARY KEY, v", 1, pzErr
  364. );
  365. }
  366. if( rc==SQLITE_OK ){
  367. rc = sqlite3Fts5StorageConfigValue(p, "version", 0, FTS5_CURRENT_VERSION);
  368. }
  369. }
  370. if( rc ){
  371. sqlite3Fts5StorageClose(p);
  372. *pp = 0;
  373. }
  374. return rc;
  375. }
  376. /*
  377. ** Close a handle opened by an earlier call to sqlite3Fts5StorageOpen().
  378. */
  379. int sqlite3Fts5StorageClose(Fts5Storage *p){
  380. int rc = SQLITE_OK;
  381. if( p ){
  382. int i;
  383. /* Finalize all SQL statements */
  384. for(i=0; i<ArraySize(p->aStmt); i++){
  385. sqlite3_finalize(p->aStmt[i]);
  386. }
  387. sqlite3_free(p);
  388. }
  389. return rc;
  390. }
  391. typedef struct Fts5InsertCtx Fts5InsertCtx;
  392. struct Fts5InsertCtx {
  393. Fts5Storage *pStorage;
  394. int iCol;
  395. int szCol; /* Size of column value in tokens */
  396. };
  397. /*
  398. ** Tokenization callback used when inserting tokens into the FTS index.
  399. */
  400. static int fts5StorageInsertCallback(
  401. void *pContext, /* Pointer to Fts5InsertCtx object */
  402. int tflags,
  403. const char *pToken, /* Buffer containing token */
  404. int nToken, /* Size of token in bytes */
  405. int iUnused1, /* Start offset of token */
  406. int iUnused2 /* End offset of token */
  407. ){
  408. Fts5InsertCtx *pCtx = (Fts5InsertCtx*)pContext;
  409. Fts5Index *pIdx = pCtx->pStorage->pIndex;
  410. UNUSED_PARAM2(iUnused1, iUnused2);
  411. if( nToken>FTS5_MAX_TOKEN_SIZE ) nToken = FTS5_MAX_TOKEN_SIZE;
  412. if( (tflags & FTS5_TOKEN_COLOCATED)==0 || pCtx->szCol==0 ){
  413. pCtx->szCol++;
  414. }
  415. return sqlite3Fts5IndexWrite(pIdx, pCtx->iCol, pCtx->szCol-1, pToken, nToken);
  416. }
  417. /*
  418. ** This function is used as part of an UPDATE statement that modifies the
  419. ** rowid of a row. In that case, this function is called first to set
  420. ** Fts5Storage.pSavedRow to point to a statement that may be used to
  421. ** access the original values of the row being deleted - iDel.
  422. **
  423. ** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
  424. ** It is not considered an error if row iDel does not exist. In this case
  425. ** pSavedRow is not set and SQLITE_OK returned.
  426. */
  427. int sqlite3Fts5StorageFindDeleteRow(Fts5Storage *p, i64 iDel){
  428. int rc = SQLITE_OK;
  429. sqlite3_stmt *pSeek = 0;
  430. assert( p->pSavedRow==0 );
  431. rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP+1, &pSeek, 0);
  432. if( rc==SQLITE_OK ){
  433. sqlite3_bind_int64(pSeek, 1, iDel);
  434. if( sqlite3_step(pSeek)!=SQLITE_ROW ){
  435. rc = sqlite3_reset(pSeek);
  436. }else{
  437. p->pSavedRow = pSeek;
  438. }
  439. }
  440. return rc;
  441. }
  442. /*
  443. ** If a row with rowid iDel is present in the %_content table, add the
  444. ** delete-markers to the FTS index necessary to delete it. Do not actually
  445. ** remove the %_content row at this time though.
  446. **
  447. ** If parameter bSaveRow is true, then Fts5Storage.pSavedRow is left
  448. ** pointing to a statement (FTS5_STMT_LOOKUP2) that may be used to access
  449. ** the original values of the row being deleted. This is used by UPDATE
  450. ** statements.
  451. */
  452. static int fts5StorageDeleteFromIndex(
  453. Fts5Storage *p,
  454. i64 iDel,
  455. sqlite3_value **apVal,
  456. int bSaveRow /* True to set pSavedRow */
  457. ){
  458. Fts5Config *pConfig = p->pConfig;
  459. sqlite3_stmt *pSeek = 0; /* SELECT to read row iDel from %_data */
  460. int rc = SQLITE_OK; /* Return code */
  461. int rc2; /* sqlite3_reset() return code */
  462. int iCol;
  463. Fts5InsertCtx ctx;
  464. assert( bSaveRow==0 || apVal==0 );
  465. assert( bSaveRow==0 || bSaveRow==1 );
  466. assert( FTS5_STMT_LOOKUP2==FTS5_STMT_LOOKUP+1 );
  467. if( apVal==0 ){
  468. if( p->pSavedRow && bSaveRow ){
  469. pSeek = p->pSavedRow;
  470. p->pSavedRow = 0;
  471. }else{
  472. rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP+bSaveRow, &pSeek, 0);
  473. if( rc!=SQLITE_OK ) return rc;
  474. sqlite3_bind_int64(pSeek, 1, iDel);
  475. if( sqlite3_step(pSeek)!=SQLITE_ROW ){
  476. return sqlite3_reset(pSeek);
  477. }
  478. }
  479. }
  480. ctx.pStorage = p;
  481. ctx.iCol = -1;
  482. for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){
  483. if( pConfig->abUnindexed[iCol-1]==0 ){
  484. sqlite3_value *pVal = 0;
  485. const char *pText = 0;
  486. int nText = 0;
  487. const char *pLoc = 0;
  488. int nLoc = 0;
  489. assert( pSeek==0 || apVal==0 );
  490. assert( pSeek!=0 || apVal!=0 );
  491. if( pSeek ){
  492. pVal = sqlite3_column_value(pSeek, iCol);
  493. }else{
  494. pVal = apVal[iCol-1];
  495. }
  496. if( pConfig->bLocale && sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
  497. rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
  498. }else{
  499. pText = (const char*)sqlite3_value_text(pVal);
  500. nText = sqlite3_value_bytes(pVal);
  501. if( pConfig->bLocale && pSeek ){
  502. pLoc = (const char*)sqlite3_column_text(pSeek, iCol + pConfig->nCol);
  503. nLoc = sqlite3_column_bytes(pSeek, iCol + pConfig->nCol);
  504. }
  505. }
  506. if( rc==SQLITE_OK ){
  507. sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
  508. ctx.szCol = 0;
  509. rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT,
  510. pText, nText, (void*)&ctx, fts5StorageInsertCallback
  511. );
  512. p->aTotalSize[iCol-1] -= (i64)ctx.szCol;
  513. if( rc==SQLITE_OK && p->aTotalSize[iCol-1]<0 ){
  514. rc = FTS5_CORRUPT;
  515. }
  516. sqlite3Fts5ClearLocale(pConfig);
  517. }
  518. }
  519. }
  520. if( rc==SQLITE_OK && p->nTotalRow<1 ){
  521. rc = FTS5_CORRUPT;
  522. }else{
  523. p->nTotalRow--;
  524. }
  525. if( rc==SQLITE_OK && bSaveRow ){
  526. assert( p->pSavedRow==0 );
  527. p->pSavedRow = pSeek;
  528. }else{
  529. rc2 = sqlite3_reset(pSeek);
  530. if( rc==SQLITE_OK ) rc = rc2;
  531. }
  532. return rc;
  533. }
  534. /*
  535. ** Reset any saved statement pSavedRow. Zero pSavedRow as well. This
  536. ** should be called by the xUpdate() method of the fts5 table before
  537. ** returning from any operation that may have set Fts5Storage.pSavedRow.
  538. */
  539. void sqlite3Fts5StorageReleaseDeleteRow(Fts5Storage *pStorage){
  540. assert( pStorage->pSavedRow==0
  541. || pStorage->pSavedRow==pStorage->aStmt[FTS5_STMT_LOOKUP2]
  542. );
  543. sqlite3_reset(pStorage->pSavedRow);
  544. pStorage->pSavedRow = 0;
  545. }
  546. /*
  547. ** This function is called to process a DELETE on a contentless_delete=1
  548. ** table. It adds the tombstone required to delete the entry with rowid
  549. ** iDel. If successful, SQLITE_OK is returned. Or, if an error occurs,
  550. ** an SQLite error code.
  551. */
  552. static int fts5StorageContentlessDelete(Fts5Storage *p, i64 iDel){
  553. i64 iOrigin = 0;
  554. sqlite3_stmt *pLookup = 0;
  555. int rc = SQLITE_OK;
  556. assert( p->pConfig->bContentlessDelete );
  557. assert( p->pConfig->eContent==FTS5_CONTENT_NONE
  558. || p->pConfig->eContent==FTS5_CONTENT_UNINDEXED
  559. );
  560. /* Look up the origin of the document in the %_docsize table. Store
  561. ** this in stack variable iOrigin. */
  562. rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP_DOCSIZE, &pLookup, 0);
  563. if( rc==SQLITE_OK ){
  564. sqlite3_bind_int64(pLookup, 1, iDel);
  565. if( SQLITE_ROW==sqlite3_step(pLookup) ){
  566. iOrigin = sqlite3_column_int64(pLookup, 1);
  567. }
  568. rc = sqlite3_reset(pLookup);
  569. }
  570. if( rc==SQLITE_OK && iOrigin!=0 ){
  571. rc = sqlite3Fts5IndexContentlessDelete(p->pIndex, iOrigin, iDel);
  572. }
  573. return rc;
  574. }
  575. /*
  576. ** Insert a record into the %_docsize table. Specifically, do:
  577. **
  578. ** INSERT OR REPLACE INTO %_docsize(id, sz) VALUES(iRowid, pBuf);
  579. **
  580. ** If there is no %_docsize table (as happens if the columnsize=0 option
  581. ** is specified when the FTS5 table is created), this function is a no-op.
  582. */
  583. static int fts5StorageInsertDocsize(
  584. Fts5Storage *p, /* Storage module to write to */
  585. i64 iRowid, /* id value */
  586. Fts5Buffer *pBuf /* sz value */
  587. ){
  588. int rc = SQLITE_OK;
  589. if( p->pConfig->bColumnsize ){
  590. sqlite3_stmt *pReplace = 0;
  591. rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_DOCSIZE, &pReplace, 0);
  592. if( rc==SQLITE_OK ){
  593. sqlite3_bind_int64(pReplace, 1, iRowid);
  594. if( p->pConfig->bContentlessDelete ){
  595. i64 iOrigin = 0;
  596. rc = sqlite3Fts5IndexGetOrigin(p->pIndex, &iOrigin);
  597. sqlite3_bind_int64(pReplace, 3, iOrigin);
  598. }
  599. }
  600. if( rc==SQLITE_OK ){
  601. sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC);
  602. sqlite3_step(pReplace);
  603. rc = sqlite3_reset(pReplace);
  604. sqlite3_bind_null(pReplace, 2);
  605. }
  606. }
  607. return rc;
  608. }
  609. /*
  610. ** Load the contents of the "averages" record from disk into the
  611. ** p->nTotalRow and p->aTotalSize[] variables. If successful, and if
  612. ** argument bCache is true, set the p->bTotalsValid flag to indicate
  613. ** that the contents of aTotalSize[] and nTotalRow are valid until
  614. ** further notice.
  615. **
  616. ** Return SQLITE_OK if successful, or an SQLite error code if an error
  617. ** occurs.
  618. */
  619. static int fts5StorageLoadTotals(Fts5Storage *p, int bCache){
  620. int rc = SQLITE_OK;
  621. if( p->bTotalsValid==0 ){
  622. rc = sqlite3Fts5IndexGetAverages(p->pIndex, &p->nTotalRow, p->aTotalSize);
  623. p->bTotalsValid = bCache;
  624. }
  625. return rc;
  626. }
  627. /*
  628. ** Store the current contents of the p->nTotalRow and p->aTotalSize[]
  629. ** variables in the "averages" record on disk.
  630. **
  631. ** Return SQLITE_OK if successful, or an SQLite error code if an error
  632. ** occurs.
  633. */
  634. static int fts5StorageSaveTotals(Fts5Storage *p){
  635. int nCol = p->pConfig->nCol;
  636. int i;
  637. Fts5Buffer buf;
  638. int rc = SQLITE_OK;
  639. memset(&buf, 0, sizeof(buf));
  640. sqlite3Fts5BufferAppendVarint(&rc, &buf, p->nTotalRow);
  641. for(i=0; i<nCol; i++){
  642. sqlite3Fts5BufferAppendVarint(&rc, &buf, p->aTotalSize[i]);
  643. }
  644. if( rc==SQLITE_OK ){
  645. rc = sqlite3Fts5IndexSetAverages(p->pIndex, buf.p, buf.n);
  646. }
  647. sqlite3_free(buf.p);
  648. return rc;
  649. }
  650. /*
  651. ** Remove a row from the FTS table.
  652. */
  653. int sqlite3Fts5StorageDelete(
  654. Fts5Storage *p, /* Storage object */
  655. i64 iDel, /* Rowid to delete from table */
  656. sqlite3_value **apVal, /* Optional - values to remove from index */
  657. int bSaveRow /* If true, set pSavedRow for deleted row */
  658. ){
  659. Fts5Config *pConfig = p->pConfig;
  660. int rc;
  661. sqlite3_stmt *pDel = 0;
  662. assert( pConfig->eContent!=FTS5_CONTENT_NORMAL || apVal==0 );
  663. rc = fts5StorageLoadTotals(p, 1);
  664. /* Delete the index records */
  665. if( rc==SQLITE_OK ){
  666. rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 1, iDel);
  667. }
  668. if( rc==SQLITE_OK ){
  669. if( p->pConfig->bContentlessDelete ){
  670. rc = fts5StorageContentlessDelete(p, iDel);
  671. if( rc==SQLITE_OK
  672. && bSaveRow
  673. && p->pConfig->eContent==FTS5_CONTENT_UNINDEXED
  674. ){
  675. rc = sqlite3Fts5StorageFindDeleteRow(p, iDel);
  676. }
  677. }else{
  678. rc = fts5StorageDeleteFromIndex(p, iDel, apVal, bSaveRow);
  679. }
  680. }
  681. /* Delete the %_docsize record */
  682. if( rc==SQLITE_OK && pConfig->bColumnsize ){
  683. rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_DOCSIZE, &pDel, 0);
  684. if( rc==SQLITE_OK ){
  685. sqlite3_bind_int64(pDel, 1, iDel);
  686. sqlite3_step(pDel);
  687. rc = sqlite3_reset(pDel);
  688. }
  689. }
  690. /* Delete the %_content record */
  691. if( pConfig->eContent==FTS5_CONTENT_NORMAL
  692. || pConfig->eContent==FTS5_CONTENT_UNINDEXED
  693. ){
  694. if( rc==SQLITE_OK ){
  695. rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_CONTENT, &pDel, 0);
  696. }
  697. if( rc==SQLITE_OK ){
  698. sqlite3_bind_int64(pDel, 1, iDel);
  699. sqlite3_step(pDel);
  700. rc = sqlite3_reset(pDel);
  701. }
  702. }
  703. return rc;
  704. }
  705. /*
  706. ** Delete all entries in the FTS5 index.
  707. */
  708. int sqlite3Fts5StorageDeleteAll(Fts5Storage *p){
  709. Fts5Config *pConfig = p->pConfig;
  710. int rc;
  711. p->bTotalsValid = 0;
  712. /* Delete the contents of the %_data and %_docsize tables. */
  713. rc = fts5ExecPrintf(pConfig->db, 0,
  714. "DELETE FROM %Q.'%q_data';"
  715. "DELETE FROM %Q.'%q_idx';",
  716. pConfig->zDb, pConfig->zName,
  717. pConfig->zDb, pConfig->zName
  718. );
  719. if( rc==SQLITE_OK && pConfig->bColumnsize ){
  720. rc = fts5ExecPrintf(pConfig->db, 0,
  721. "DELETE FROM %Q.'%q_docsize';", pConfig->zDb, pConfig->zName
  722. );
  723. }
  724. if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_UNINDEXED ){
  725. rc = fts5ExecPrintf(pConfig->db, 0,
  726. "DELETE FROM %Q.'%q_content';", pConfig->zDb, pConfig->zName
  727. );
  728. }
  729. /* Reinitialize the %_data table. This call creates the initial structure
  730. ** and averages records. */
  731. if( rc==SQLITE_OK ){
  732. rc = sqlite3Fts5IndexReinit(p->pIndex);
  733. }
  734. if( rc==SQLITE_OK ){
  735. rc = sqlite3Fts5StorageConfigValue(p, "version", 0, FTS5_CURRENT_VERSION);
  736. }
  737. return rc;
  738. }
  739. int sqlite3Fts5StorageRebuild(Fts5Storage *p){
  740. Fts5Buffer buf = {0,0,0};
  741. Fts5Config *pConfig = p->pConfig;
  742. sqlite3_stmt *pScan = 0;
  743. Fts5InsertCtx ctx;
  744. int rc, rc2;
  745. memset(&ctx, 0, sizeof(Fts5InsertCtx));
  746. ctx.pStorage = p;
  747. rc = sqlite3Fts5StorageDeleteAll(p);
  748. if( rc==SQLITE_OK ){
  749. rc = fts5StorageLoadTotals(p, 1);
  750. }
  751. if( rc==SQLITE_OK ){
  752. rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, pConfig->pzErrmsg);
  753. }
  754. while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pScan) ){
  755. i64 iRowid = sqlite3_column_int64(pScan, 0);
  756. sqlite3Fts5BufferZero(&buf);
  757. rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 0, iRowid);
  758. for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
  759. ctx.szCol = 0;
  760. if( pConfig->abUnindexed[ctx.iCol]==0 ){
  761. int nText = 0; /* Size of pText in bytes */
  762. const char *pText = 0; /* Pointer to buffer containing text value */
  763. int nLoc = 0; /* Size of pLoc in bytes */
  764. const char *pLoc = 0; /* Pointer to buffer containing text value */
  765. sqlite3_value *pVal = sqlite3_column_value(pScan, ctx.iCol+1);
  766. if( pConfig->eContent==FTS5_CONTENT_EXTERNAL
  767. && sqlite3Fts5IsLocaleValue(pConfig, pVal)
  768. ){
  769. rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
  770. }else{
  771. pText = (const char*)sqlite3_value_text(pVal);
  772. nText = sqlite3_value_bytes(pVal);
  773. if( pConfig->bLocale ){
  774. int iCol = ctx.iCol + 1 + pConfig->nCol;
  775. pLoc = (const char*)sqlite3_column_text(pScan, iCol);
  776. nLoc = sqlite3_column_bytes(pScan, iCol);
  777. }
  778. }
  779. if( rc==SQLITE_OK ){
  780. sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
  781. rc = sqlite3Fts5Tokenize(pConfig,
  782. FTS5_TOKENIZE_DOCUMENT,
  783. pText, nText,
  784. (void*)&ctx,
  785. fts5StorageInsertCallback
  786. );
  787. sqlite3Fts5ClearLocale(pConfig);
  788. }
  789. }
  790. sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol);
  791. p->aTotalSize[ctx.iCol] += (i64)ctx.szCol;
  792. }
  793. p->nTotalRow++;
  794. if( rc==SQLITE_OK ){
  795. rc = fts5StorageInsertDocsize(p, iRowid, &buf);
  796. }
  797. }
  798. sqlite3_free(buf.p);
  799. rc2 = sqlite3_reset(pScan);
  800. if( rc==SQLITE_OK ) rc = rc2;
  801. /* Write the averages record */
  802. if( rc==SQLITE_OK ){
  803. rc = fts5StorageSaveTotals(p);
  804. }
  805. return rc;
  806. }
  807. int sqlite3Fts5StorageOptimize(Fts5Storage *p){
  808. return sqlite3Fts5IndexOptimize(p->pIndex);
  809. }
  810. int sqlite3Fts5StorageMerge(Fts5Storage *p, int nMerge){
  811. return sqlite3Fts5IndexMerge(p->pIndex, nMerge);
  812. }
  813. int sqlite3Fts5StorageReset(Fts5Storage *p){
  814. return sqlite3Fts5IndexReset(p->pIndex);
  815. }
  816. /*
  817. ** Allocate a new rowid. This is used for "external content" tables when
  818. ** a NULL value is inserted into the rowid column. The new rowid is allocated
  819. ** by inserting a dummy row into the %_docsize table. The dummy will be
  820. ** overwritten later.
  821. **
  822. ** If the %_docsize table does not exist, SQLITE_MISMATCH is returned. In
  823. ** this case the user is required to provide a rowid explicitly.
  824. */
  825. static int fts5StorageNewRowid(Fts5Storage *p, i64 *piRowid){
  826. int rc = SQLITE_MISMATCH;
  827. if( p->pConfig->bColumnsize ){
  828. sqlite3_stmt *pReplace = 0;
  829. rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_DOCSIZE, &pReplace, 0);
  830. if( rc==SQLITE_OK ){
  831. sqlite3_bind_null(pReplace, 1);
  832. sqlite3_bind_null(pReplace, 2);
  833. sqlite3_step(pReplace);
  834. rc = sqlite3_reset(pReplace);
  835. }
  836. if( rc==SQLITE_OK ){
  837. *piRowid = sqlite3_last_insert_rowid(p->pConfig->db);
  838. }
  839. }
  840. return rc;
  841. }
  842. /*
  843. ** Insert a new row into the FTS content table.
  844. */
  845. int sqlite3Fts5StorageContentInsert(
  846. Fts5Storage *p,
  847. int bReplace, /* True to use REPLACE instead of INSERT */
  848. sqlite3_value **apVal,
  849. i64 *piRowid
  850. ){
  851. Fts5Config *pConfig = p->pConfig;
  852. int rc = SQLITE_OK;
  853. /* Insert the new row into the %_content table. */
  854. if( pConfig->eContent!=FTS5_CONTENT_NORMAL
  855. && pConfig->eContent!=FTS5_CONTENT_UNINDEXED
  856. ){
  857. if( sqlite3_value_type(apVal[1])==SQLITE_INTEGER ){
  858. *piRowid = sqlite3_value_int64(apVal[1]);
  859. }else{
  860. rc = fts5StorageNewRowid(p, piRowid);
  861. }
  862. }else{
  863. sqlite3_stmt *pInsert = 0; /* Statement to write %_content table */
  864. int i; /* Counter variable */
  865. assert( FTS5_STMT_INSERT_CONTENT+1==FTS5_STMT_REPLACE_CONTENT );
  866. assert( bReplace==0 || bReplace==1 );
  867. rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT+bReplace, &pInsert, 0);
  868. if( pInsert ) sqlite3_clear_bindings(pInsert);
  869. /* Bind the rowid value */
  870. sqlite3_bind_value(pInsert, 1, apVal[1]);
  871. /* Loop through values for user-defined columns. i=2 is the leftmost
  872. ** user-defined column. As is column 1 of pSavedRow. */
  873. for(i=2; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
  874. int bUnindexed = pConfig->abUnindexed[i-2];
  875. if( pConfig->eContent==FTS5_CONTENT_NORMAL || bUnindexed ){
  876. sqlite3_value *pVal = apVal[i];
  877. if( sqlite3_value_nochange(pVal) && p->pSavedRow ){
  878. /* This is an UPDATE statement, and user-defined column (i-2) was not
  879. ** modified. Retrieve the value from Fts5Storage.pSavedRow. */
  880. pVal = sqlite3_column_value(p->pSavedRow, i-1);
  881. if( pConfig->bLocale && bUnindexed==0 ){
  882. sqlite3_bind_value(pInsert, pConfig->nCol + i,
  883. sqlite3_column_value(p->pSavedRow, pConfig->nCol + i - 1)
  884. );
  885. }
  886. }else if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
  887. const char *pText = 0;
  888. const char *pLoc = 0;
  889. int nText = 0;
  890. int nLoc = 0;
  891. assert( pConfig->bLocale );
  892. rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
  893. if( rc==SQLITE_OK ){
  894. sqlite3_bind_text(pInsert, i, pText, nText, SQLITE_TRANSIENT);
  895. if( bUnindexed==0 ){
  896. int iLoc = pConfig->nCol + i;
  897. sqlite3_bind_text(pInsert, iLoc, pLoc, nLoc, SQLITE_TRANSIENT);
  898. }
  899. }
  900. continue;
  901. }
  902. rc = sqlite3_bind_value(pInsert, i, pVal);
  903. }
  904. }
  905. if( rc==SQLITE_OK ){
  906. sqlite3_step(pInsert);
  907. rc = sqlite3_reset(pInsert);
  908. }
  909. *piRowid = sqlite3_last_insert_rowid(pConfig->db);
  910. }
  911. return rc;
  912. }
  913. /*
  914. ** Insert new entries into the FTS index and %_docsize table.
  915. */
  916. int sqlite3Fts5StorageIndexInsert(
  917. Fts5Storage *p,
  918. sqlite3_value **apVal,
  919. i64 iRowid
  920. ){
  921. Fts5Config *pConfig = p->pConfig;
  922. int rc = SQLITE_OK; /* Return code */
  923. Fts5InsertCtx ctx; /* Tokenization callback context object */
  924. Fts5Buffer buf; /* Buffer used to build up %_docsize blob */
  925. memset(&buf, 0, sizeof(Fts5Buffer));
  926. ctx.pStorage = p;
  927. rc = fts5StorageLoadTotals(p, 1);
  928. if( rc==SQLITE_OK ){
  929. rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 0, iRowid);
  930. }
  931. for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
  932. ctx.szCol = 0;
  933. if( pConfig->abUnindexed[ctx.iCol]==0 ){
  934. int nText = 0; /* Size of pText in bytes */
  935. const char *pText = 0; /* Pointer to buffer containing text value */
  936. int nLoc = 0; /* Size of pText in bytes */
  937. const char *pLoc = 0; /* Pointer to buffer containing text value */
  938. sqlite3_value *pVal = apVal[ctx.iCol+2];
  939. if( p->pSavedRow && sqlite3_value_nochange(pVal) ){
  940. pVal = sqlite3_column_value(p->pSavedRow, ctx.iCol+1);
  941. if( pConfig->eContent==FTS5_CONTENT_NORMAL && pConfig->bLocale ){
  942. int iCol = ctx.iCol + 1 + pConfig->nCol;
  943. pLoc = (const char*)sqlite3_column_text(p->pSavedRow, iCol);
  944. nLoc = sqlite3_column_bytes(p->pSavedRow, iCol);
  945. }
  946. }else{
  947. pVal = apVal[ctx.iCol+2];
  948. }
  949. if( pConfig->bLocale && sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
  950. rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
  951. }else{
  952. pText = (const char*)sqlite3_value_text(pVal);
  953. nText = sqlite3_value_bytes(pVal);
  954. }
  955. if( rc==SQLITE_OK ){
  956. sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
  957. rc = sqlite3Fts5Tokenize(pConfig,
  958. FTS5_TOKENIZE_DOCUMENT, pText, nText, (void*)&ctx,
  959. fts5StorageInsertCallback
  960. );
  961. sqlite3Fts5ClearLocale(pConfig);
  962. }
  963. }
  964. sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol);
  965. p->aTotalSize[ctx.iCol] += (i64)ctx.szCol;
  966. }
  967. p->nTotalRow++;
  968. /* Write the %_docsize record */
  969. if( rc==SQLITE_OK ){
  970. rc = fts5StorageInsertDocsize(p, iRowid, &buf);
  971. }
  972. sqlite3_free(buf.p);
  973. return rc;
  974. }
  975. static int fts5StorageCount(Fts5Storage *p, const char *zSuffix, i64 *pnRow){
  976. Fts5Config *pConfig = p->pConfig;
  977. char *zSql;
  978. int rc;
  979. zSql = sqlite3_mprintf("SELECT count(*) FROM %Q.'%q_%s'",
  980. pConfig->zDb, pConfig->zName, zSuffix
  981. );
  982. if( zSql==0 ){
  983. rc = SQLITE_NOMEM;
  984. }else{
  985. sqlite3_stmt *pCnt = 0;
  986. rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pCnt, 0);
  987. if( rc==SQLITE_OK ){
  988. if( SQLITE_ROW==sqlite3_step(pCnt) ){
  989. *pnRow = sqlite3_column_int64(pCnt, 0);
  990. }
  991. rc = sqlite3_finalize(pCnt);
  992. }
  993. }
  994. sqlite3_free(zSql);
  995. return rc;
  996. }
  997. /*
  998. ** Context object used by sqlite3Fts5StorageIntegrity().
  999. */
  1000. typedef struct Fts5IntegrityCtx Fts5IntegrityCtx;
  1001. struct Fts5IntegrityCtx {
  1002. i64 iRowid;
  1003. int iCol;
  1004. int szCol;
  1005. u64 cksum;
  1006. Fts5Termset *pTermset;
  1007. Fts5Config *pConfig;
  1008. };
  1009. /*
  1010. ** Tokenization callback used by integrity check.
  1011. */
  1012. static int fts5StorageIntegrityCallback(
  1013. void *pContext, /* Pointer to Fts5IntegrityCtx object */
  1014. int tflags,
  1015. const char *pToken, /* Buffer containing token */
  1016. int nToken, /* Size of token in bytes */
  1017. int iUnused1, /* Start offset of token */
  1018. int iUnused2 /* End offset of token */
  1019. ){
  1020. Fts5IntegrityCtx *pCtx = (Fts5IntegrityCtx*)pContext;
  1021. Fts5Termset *pTermset = pCtx->pTermset;
  1022. int bPresent;
  1023. int ii;
  1024. int rc = SQLITE_OK;
  1025. int iPos;
  1026. int iCol;
  1027. UNUSED_PARAM2(iUnused1, iUnused2);
  1028. if( nToken>FTS5_MAX_TOKEN_SIZE ) nToken = FTS5_MAX_TOKEN_SIZE;
  1029. if( (tflags & FTS5_TOKEN_COLOCATED)==0 || pCtx->szCol==0 ){
  1030. pCtx->szCol++;
  1031. }
  1032. switch( pCtx->pConfig->eDetail ){
  1033. case FTS5_DETAIL_FULL:
  1034. iPos = pCtx->szCol-1;
  1035. iCol = pCtx->iCol;
  1036. break;
  1037. case FTS5_DETAIL_COLUMNS:
  1038. iPos = pCtx->iCol;
  1039. iCol = 0;
  1040. break;
  1041. default:
  1042. assert( pCtx->pConfig->eDetail==FTS5_DETAIL_NONE );
  1043. iPos = 0;
  1044. iCol = 0;
  1045. break;
  1046. }
  1047. rc = sqlite3Fts5TermsetAdd(pTermset, 0, pToken, nToken, &bPresent);
  1048. if( rc==SQLITE_OK && bPresent==0 ){
  1049. pCtx->cksum ^= sqlite3Fts5IndexEntryCksum(
  1050. pCtx->iRowid, iCol, iPos, 0, pToken, nToken
  1051. );
  1052. }
  1053. for(ii=0; rc==SQLITE_OK && ii<pCtx->pConfig->nPrefix; ii++){
  1054. const int nChar = pCtx->pConfig->aPrefix[ii];
  1055. int nByte = sqlite3Fts5IndexCharlenToBytelen(pToken, nToken, nChar);
  1056. if( nByte ){
  1057. rc = sqlite3Fts5TermsetAdd(pTermset, ii+1, pToken, nByte, &bPresent);
  1058. if( bPresent==0 ){
  1059. pCtx->cksum ^= sqlite3Fts5IndexEntryCksum(
  1060. pCtx->iRowid, iCol, iPos, ii+1, pToken, nByte
  1061. );
  1062. }
  1063. }
  1064. }
  1065. return rc;
  1066. }
  1067. /*
  1068. ** Check that the contents of the FTS index match that of the %_content
  1069. ** table. Return SQLITE_OK if they do, or SQLITE_CORRUPT if not. Return
  1070. ** some other SQLite error code if an error occurs while attempting to
  1071. ** determine this.
  1072. */
  1073. int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg){
  1074. Fts5Config *pConfig = p->pConfig;
  1075. int rc = SQLITE_OK; /* Return code */
  1076. int *aColSize; /* Array of size pConfig->nCol */
  1077. i64 *aTotalSize; /* Array of size pConfig->nCol */
  1078. Fts5IntegrityCtx ctx;
  1079. sqlite3_stmt *pScan;
  1080. int bUseCksum;
  1081. memset(&ctx, 0, sizeof(Fts5IntegrityCtx));
  1082. ctx.pConfig = p->pConfig;
  1083. aTotalSize = (i64*)sqlite3_malloc64(pConfig->nCol*(sizeof(int)+sizeof(i64)));
  1084. if( !aTotalSize ) return SQLITE_NOMEM;
  1085. aColSize = (int*)&aTotalSize[pConfig->nCol];
  1086. memset(aTotalSize, 0, sizeof(i64) * pConfig->nCol);
  1087. bUseCksum = (pConfig->eContent==FTS5_CONTENT_NORMAL
  1088. || (pConfig->eContent==FTS5_CONTENT_EXTERNAL && iArg)
  1089. );
  1090. if( bUseCksum ){
  1091. /* Generate the expected index checksum based on the contents of the
  1092. ** %_content table. This block stores the checksum in ctx.cksum. */
  1093. rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0);
  1094. if( rc==SQLITE_OK ){
  1095. int rc2;
  1096. while( SQLITE_ROW==sqlite3_step(pScan) ){
  1097. int i;
  1098. ctx.iRowid = sqlite3_column_int64(pScan, 0);
  1099. ctx.szCol = 0;
  1100. if( pConfig->bColumnsize ){
  1101. rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize);
  1102. }
  1103. if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_NONE ){
  1104. rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
  1105. }
  1106. for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
  1107. if( pConfig->abUnindexed[i]==0 ){
  1108. const char *pText = 0;
  1109. int nText = 0;
  1110. const char *pLoc = 0;
  1111. int nLoc = 0;
  1112. sqlite3_value *pVal = sqlite3_column_value(pScan, i+1);
  1113. if( pConfig->eContent==FTS5_CONTENT_EXTERNAL
  1114. && sqlite3Fts5IsLocaleValue(pConfig, pVal)
  1115. ){
  1116. rc = sqlite3Fts5DecodeLocaleValue(
  1117. pVal, &pText, &nText, &pLoc, &nLoc
  1118. );
  1119. }else{
  1120. if( pConfig->eContent==FTS5_CONTENT_NORMAL && pConfig->bLocale ){
  1121. int iCol = i + 1 + pConfig->nCol;
  1122. pLoc = (const char*)sqlite3_column_text(pScan, iCol);
  1123. nLoc = sqlite3_column_bytes(pScan, iCol);
  1124. }
  1125. pText = (const char*)sqlite3_value_text(pVal);
  1126. nText = sqlite3_value_bytes(pVal);
  1127. }
  1128. ctx.iCol = i;
  1129. ctx.szCol = 0;
  1130. if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
  1131. rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
  1132. }
  1133. if( rc==SQLITE_OK ){
  1134. sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
  1135. rc = sqlite3Fts5Tokenize(pConfig,
  1136. FTS5_TOKENIZE_DOCUMENT,
  1137. pText, nText,
  1138. (void*)&ctx,
  1139. fts5StorageIntegrityCallback
  1140. );
  1141. sqlite3Fts5ClearLocale(pConfig);
  1142. }
  1143. /* If this is not a columnsize=0 database, check that the number
  1144. ** of tokens in the value matches the aColSize[] value read from
  1145. ** the %_docsize table. */
  1146. if( rc==SQLITE_OK
  1147. && pConfig->bColumnsize
  1148. && ctx.szCol!=aColSize[i]
  1149. ){
  1150. rc = FTS5_CORRUPT;
  1151. }
  1152. aTotalSize[i] += ctx.szCol;
  1153. if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
  1154. sqlite3Fts5TermsetFree(ctx.pTermset);
  1155. ctx.pTermset = 0;
  1156. }
  1157. }
  1158. }
  1159. sqlite3Fts5TermsetFree(ctx.pTermset);
  1160. ctx.pTermset = 0;
  1161. if( rc!=SQLITE_OK ) break;
  1162. }
  1163. rc2 = sqlite3_reset(pScan);
  1164. if( rc==SQLITE_OK ) rc = rc2;
  1165. }
  1166. /* Test that the "totals" (sometimes called "averages") record looks Ok */
  1167. if( rc==SQLITE_OK ){
  1168. int i;
  1169. rc = fts5StorageLoadTotals(p, 0);
  1170. for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
  1171. if( p->aTotalSize[i]!=aTotalSize[i] ) rc = FTS5_CORRUPT;
  1172. }
  1173. }
  1174. /* Check that the %_docsize and %_content tables contain the expected
  1175. ** number of rows. */
  1176. if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
  1177. i64 nRow = 0;
  1178. rc = fts5StorageCount(p, "content", &nRow);
  1179. if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
  1180. }
  1181. if( rc==SQLITE_OK && pConfig->bColumnsize ){
  1182. i64 nRow = 0;
  1183. rc = fts5StorageCount(p, "docsize", &nRow);
  1184. if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
  1185. }
  1186. }
  1187. /* Pass the expected checksum down to the FTS index module. It will
  1188. ** verify, amongst other things, that it matches the checksum generated by
  1189. ** inspecting the index itself. */
  1190. if( rc==SQLITE_OK ){
  1191. rc = sqlite3Fts5IndexIntegrityCheck(p->pIndex, ctx.cksum, bUseCksum);
  1192. }
  1193. sqlite3_free(aTotalSize);
  1194. return rc;
  1195. }
  1196. /*
  1197. ** Obtain an SQLite statement handle that may be used to read data from the
  1198. ** %_content table.
  1199. */
  1200. int sqlite3Fts5StorageStmt(
  1201. Fts5Storage *p,
  1202. int eStmt,
  1203. sqlite3_stmt **pp,
  1204. char **pzErrMsg
  1205. ){
  1206. int rc;
  1207. assert( eStmt==FTS5_STMT_SCAN_ASC
  1208. || eStmt==FTS5_STMT_SCAN_DESC
  1209. || eStmt==FTS5_STMT_LOOKUP
  1210. );
  1211. rc = fts5StorageGetStmt(p, eStmt, pp, pzErrMsg);
  1212. if( rc==SQLITE_OK ){
  1213. assert( p->aStmt[eStmt]==*pp );
  1214. p->aStmt[eStmt] = 0;
  1215. }
  1216. return rc;
  1217. }
  1218. /*
  1219. ** Release an SQLite statement handle obtained via an earlier call to
  1220. ** sqlite3Fts5StorageStmt(). The eStmt parameter passed to this function
  1221. ** must match that passed to the sqlite3Fts5StorageStmt() call.
  1222. */
  1223. void sqlite3Fts5StorageStmtRelease(
  1224. Fts5Storage *p,
  1225. int eStmt,
  1226. sqlite3_stmt *pStmt
  1227. ){
  1228. assert( eStmt==FTS5_STMT_SCAN_ASC
  1229. || eStmt==FTS5_STMT_SCAN_DESC
  1230. || eStmt==FTS5_STMT_LOOKUP
  1231. );
  1232. if( p->aStmt[eStmt]==0 ){
  1233. sqlite3_reset(pStmt);
  1234. p->aStmt[eStmt] = pStmt;
  1235. }else{
  1236. sqlite3_finalize(pStmt);
  1237. }
  1238. }
  1239. static int fts5StorageDecodeSizeArray(
  1240. int *aCol, int nCol, /* Array to populate */
  1241. const u8 *aBlob, int nBlob /* Record to read varints from */
  1242. ){
  1243. int i;
  1244. int iOff = 0;
  1245. for(i=0; i<nCol; i++){
  1246. if( iOff>=nBlob ) return 1;
  1247. iOff += fts5GetVarint32(&aBlob[iOff], aCol[i]);
  1248. }
  1249. return (iOff!=nBlob);
  1250. }
  1251. /*
  1252. ** Argument aCol points to an array of integers containing one entry for
  1253. ** each table column. This function reads the %_docsize record for the
  1254. ** specified rowid and populates aCol[] with the results.
  1255. **
  1256. ** An SQLite error code is returned if an error occurs, or SQLITE_OK
  1257. ** otherwise.
  1258. */
  1259. int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol){
  1260. int nCol = p->pConfig->nCol; /* Number of user columns in table */
  1261. sqlite3_stmt *pLookup = 0; /* Statement to query %_docsize */
  1262. int rc; /* Return Code */
  1263. assert( p->pConfig->bColumnsize );
  1264. rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP_DOCSIZE, &pLookup, 0);
  1265. if( pLookup ){
  1266. int bCorrupt = 1;
  1267. assert( rc==SQLITE_OK );
  1268. sqlite3_bind_int64(pLookup, 1, iRowid);
  1269. if( SQLITE_ROW==sqlite3_step(pLookup) ){
  1270. const u8 *aBlob = sqlite3_column_blob(pLookup, 0);
  1271. int nBlob = sqlite3_column_bytes(pLookup, 0);
  1272. if( 0==fts5StorageDecodeSizeArray(aCol, nCol, aBlob, nBlob) ){
  1273. bCorrupt = 0;
  1274. }
  1275. }
  1276. rc = sqlite3_reset(pLookup);
  1277. if( bCorrupt && rc==SQLITE_OK ){
  1278. rc = FTS5_CORRUPT;
  1279. }
  1280. }else{
  1281. assert( rc!=SQLITE_OK );
  1282. }
  1283. return rc;
  1284. }
  1285. int sqlite3Fts5StorageSize(Fts5Storage *p, int iCol, i64 *pnToken){
  1286. int rc = fts5StorageLoadTotals(p, 0);
  1287. if( rc==SQLITE_OK ){
  1288. *pnToken = 0;
  1289. if( iCol<0 ){
  1290. int i;
  1291. for(i=0; i<p->pConfig->nCol; i++){
  1292. *pnToken += p->aTotalSize[i];
  1293. }
  1294. }else if( iCol<p->pConfig->nCol ){
  1295. *pnToken = p->aTotalSize[iCol];
  1296. }else{
  1297. rc = SQLITE_RANGE;
  1298. }
  1299. }
  1300. return rc;
  1301. }
  1302. int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow){
  1303. int rc = fts5StorageLoadTotals(p, 0);
  1304. if( rc==SQLITE_OK ){
  1305. /* nTotalRow being zero does not necessarily indicate a corrupt
  1306. ** database - it might be that the FTS5 table really does contain zero
  1307. ** rows. However this function is only called from the xRowCount() API,
  1308. ** and there is no way for that API to be invoked if the table contains
  1309. ** no rows. Hence the FTS5_CORRUPT return. */
  1310. *pnRow = p->nTotalRow;
  1311. if( p->nTotalRow<=0 ) rc = FTS5_CORRUPT;
  1312. }
  1313. return rc;
  1314. }
  1315. /*
  1316. ** Flush any data currently held in-memory to disk.
  1317. */
  1318. int sqlite3Fts5StorageSync(Fts5Storage *p){
  1319. int rc = SQLITE_OK;
  1320. i64 iLastRowid = sqlite3_last_insert_rowid(p->pConfig->db);
  1321. if( p->bTotalsValid ){
  1322. rc = fts5StorageSaveTotals(p);
  1323. if( rc==SQLITE_OK ){
  1324. p->bTotalsValid = 0;
  1325. }
  1326. }
  1327. if( rc==SQLITE_OK ){
  1328. rc = sqlite3Fts5IndexSync(p->pIndex);
  1329. }
  1330. sqlite3_set_last_insert_rowid(p->pConfig->db, iLastRowid);
  1331. return rc;
  1332. }
  1333. int sqlite3Fts5StorageRollback(Fts5Storage *p){
  1334. p->bTotalsValid = 0;
  1335. return sqlite3Fts5IndexRollback(p->pIndex);
  1336. }
  1337. int sqlite3Fts5StorageConfigValue(
  1338. Fts5Storage *p,
  1339. const char *z,
  1340. sqlite3_value *pVal,
  1341. int iVal
  1342. ){
  1343. sqlite3_stmt *pReplace = 0;
  1344. int rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_CONFIG, &pReplace, 0);
  1345. if( rc==SQLITE_OK ){
  1346. sqlite3_bind_text(pReplace, 1, z, -1, SQLITE_STATIC);
  1347. if( pVal ){
  1348. sqlite3_bind_value(pReplace, 2, pVal);
  1349. }else{
  1350. sqlite3_bind_int(pReplace, 2, iVal);
  1351. }
  1352. sqlite3_step(pReplace);
  1353. rc = sqlite3_reset(pReplace);
  1354. sqlite3_bind_null(pReplace, 1);
  1355. }
  1356. if( rc==SQLITE_OK && pVal ){
  1357. int iNew = p->pConfig->iCookie + 1;
  1358. rc = sqlite3Fts5IndexSetCookie(p->pIndex, iNew);
  1359. if( rc==SQLITE_OK ){
  1360. p->pConfig->iCookie = iNew;
  1361. }
  1362. }
  1363. return rc;
  1364. }