fts5_storage.c 45 KB

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