Annotation of embedaddon/sqlite3/ext/fts3/fts3_write.c, revision 1.1.1.1
1.1 misho 1: /*
2: ** 2009 Oct 23
3: **
4: ** The author disclaims copyright to this source code. In place of
5: ** a legal notice, here is a blessing:
6: **
7: ** May you do good and not evil.
8: ** May you find forgiveness for yourself and forgive others.
9: ** May you share freely, never taking more than you give.
10: **
11: ******************************************************************************
12: **
13: ** This file is part of the SQLite FTS3 extension module. Specifically,
14: ** this file contains code to insert, update and delete rows from FTS3
15: ** tables. It also contains code to merge FTS3 b-tree segments. Some
16: ** of the sub-routines used to merge segments are also used by the query
17: ** code in fts3.c.
18: */
19:
20: #include "fts3Int.h"
21: #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
22:
23: #include <string.h>
24: #include <assert.h>
25: #include <stdlib.h>
26:
27: /*
28: ** When full-text index nodes are loaded from disk, the buffer that they
29: ** are loaded into has the following number of bytes of padding at the end
30: ** of it. i.e. if a full-text index node is 900 bytes in size, then a buffer
31: ** of 920 bytes is allocated for it.
32: **
33: ** This means that if we have a pointer into a buffer containing node data,
34: ** it is always safe to read up to two varints from it without risking an
35: ** overread, even if the node data is corrupted.
36: */
37: #define FTS3_NODE_PADDING (FTS3_VARINT_MAX*2)
38:
39: /*
40: ** Under certain circumstances, b-tree nodes (doclists) can be loaded into
41: ** memory incrementally instead of all at once. This can be a big performance
42: ** win (reduced IO and CPU) if SQLite stops calling the virtual table xNext()
43: ** method before retrieving all query results (as may happen, for example,
44: ** if a query has a LIMIT clause).
45: **
46: ** Incremental loading is used for b-tree nodes FTS3_NODE_CHUNK_THRESHOLD
47: ** bytes and larger. Nodes are loaded in chunks of FTS3_NODE_CHUNKSIZE bytes.
48: ** The code is written so that the hard lower-limit for each of these values
49: ** is 1. Clearly such small values would be inefficient, but can be useful
50: ** for testing purposes.
51: **
52: ** If this module is built with SQLITE_TEST defined, these constants may
53: ** be overridden at runtime for testing purposes. File fts3_test.c contains
54: ** a Tcl interface to read and write the values.
55: */
56: #ifdef SQLITE_TEST
57: int test_fts3_node_chunksize = (4*1024);
58: int test_fts3_node_chunk_threshold = (4*1024)*4;
59: # define FTS3_NODE_CHUNKSIZE test_fts3_node_chunksize
60: # define FTS3_NODE_CHUNK_THRESHOLD test_fts3_node_chunk_threshold
61: #else
62: # define FTS3_NODE_CHUNKSIZE (4*1024)
63: # define FTS3_NODE_CHUNK_THRESHOLD (FTS3_NODE_CHUNKSIZE*4)
64: #endif
65:
66: typedef struct PendingList PendingList;
67: typedef struct SegmentNode SegmentNode;
68: typedef struct SegmentWriter SegmentWriter;
69:
70: /*
71: ** An instance of the following data structure is used to build doclists
72: ** incrementally. See function fts3PendingListAppend() for details.
73: */
74: struct PendingList {
75: int nData;
76: char *aData;
77: int nSpace;
78: sqlite3_int64 iLastDocid;
79: sqlite3_int64 iLastCol;
80: sqlite3_int64 iLastPos;
81: };
82:
83:
84: /*
85: ** Each cursor has a (possibly empty) linked list of the following objects.
86: */
87: struct Fts3DeferredToken {
88: Fts3PhraseToken *pToken; /* Pointer to corresponding expr token */
89: int iCol; /* Column token must occur in */
90: Fts3DeferredToken *pNext; /* Next in list of deferred tokens */
91: PendingList *pList; /* Doclist is assembled here */
92: };
93:
94: /*
95: ** An instance of this structure is used to iterate through the terms on
96: ** a contiguous set of segment b-tree leaf nodes. Although the details of
97: ** this structure are only manipulated by code in this file, opaque handles
98: ** of type Fts3SegReader* are also used by code in fts3.c to iterate through
99: ** terms when querying the full-text index. See functions:
100: **
101: ** sqlite3Fts3SegReaderNew()
102: ** sqlite3Fts3SegReaderFree()
103: ** sqlite3Fts3SegReaderIterate()
104: **
105: ** Methods used to manipulate Fts3SegReader structures:
106: **
107: ** fts3SegReaderNext()
108: ** fts3SegReaderFirstDocid()
109: ** fts3SegReaderNextDocid()
110: */
111: struct Fts3SegReader {
112: int iIdx; /* Index within level, or 0x7FFFFFFF for PT */
113:
114: sqlite3_int64 iStartBlock; /* Rowid of first leaf block to traverse */
115: sqlite3_int64 iLeafEndBlock; /* Rowid of final leaf block to traverse */
116: sqlite3_int64 iEndBlock; /* Rowid of final block in segment (or 0) */
117: sqlite3_int64 iCurrentBlock; /* Current leaf block (or 0) */
118:
119: char *aNode; /* Pointer to node data (or NULL) */
120: int nNode; /* Size of buffer at aNode (or 0) */
121: int nPopulate; /* If >0, bytes of buffer aNode[] loaded */
122: sqlite3_blob *pBlob; /* If not NULL, blob handle to read node */
123:
124: Fts3HashElem **ppNextElem;
125:
126: /* Variables set by fts3SegReaderNext(). These may be read directly
127: ** by the caller. They are valid from the time SegmentReaderNew() returns
128: ** until SegmentReaderNext() returns something other than SQLITE_OK
129: ** (i.e. SQLITE_DONE).
130: */
131: int nTerm; /* Number of bytes in current term */
132: char *zTerm; /* Pointer to current term */
133: int nTermAlloc; /* Allocated size of zTerm buffer */
134: char *aDoclist; /* Pointer to doclist of current entry */
135: int nDoclist; /* Size of doclist in current entry */
136:
137: /* The following variables are used by fts3SegReaderNextDocid() to iterate
138: ** through the current doclist (aDoclist/nDoclist).
139: */
140: char *pOffsetList;
141: int nOffsetList; /* For descending pending seg-readers only */
142: sqlite3_int64 iDocid;
143: };
144:
145: #define fts3SegReaderIsPending(p) ((p)->ppNextElem!=0)
146: #define fts3SegReaderIsRootOnly(p) ((p)->aNode==(char *)&(p)[1])
147:
148: /*
149: ** An instance of this structure is used to create a segment b-tree in the
150: ** database. The internal details of this type are only accessed by the
151: ** following functions:
152: **
153: ** fts3SegWriterAdd()
154: ** fts3SegWriterFlush()
155: ** fts3SegWriterFree()
156: */
157: struct SegmentWriter {
158: SegmentNode *pTree; /* Pointer to interior tree structure */
159: sqlite3_int64 iFirst; /* First slot in %_segments written */
160: sqlite3_int64 iFree; /* Next free slot in %_segments */
161: char *zTerm; /* Pointer to previous term buffer */
162: int nTerm; /* Number of bytes in zTerm */
163: int nMalloc; /* Size of malloc'd buffer at zMalloc */
164: char *zMalloc; /* Malloc'd space (possibly) used for zTerm */
165: int nSize; /* Size of allocation at aData */
166: int nData; /* Bytes of data in aData */
167: char *aData; /* Pointer to block from malloc() */
168: };
169:
170: /*
171: ** Type SegmentNode is used by the following three functions to create
172: ** the interior part of the segment b+-tree structures (everything except
173: ** the leaf nodes). These functions and type are only ever used by code
174: ** within the fts3SegWriterXXX() family of functions described above.
175: **
176: ** fts3NodeAddTerm()
177: ** fts3NodeWrite()
178: ** fts3NodeFree()
179: **
180: ** When a b+tree is written to the database (either as a result of a merge
181: ** or the pending-terms table being flushed), leaves are written into the
182: ** database file as soon as they are completely populated. The interior of
183: ** the tree is assembled in memory and written out only once all leaves have
184: ** been populated and stored. This is Ok, as the b+-tree fanout is usually
185: ** very large, meaning that the interior of the tree consumes relatively
186: ** little memory.
187: */
188: struct SegmentNode {
189: SegmentNode *pParent; /* Parent node (or NULL for root node) */
190: SegmentNode *pRight; /* Pointer to right-sibling */
191: SegmentNode *pLeftmost; /* Pointer to left-most node of this depth */
192: int nEntry; /* Number of terms written to node so far */
193: char *zTerm; /* Pointer to previous term buffer */
194: int nTerm; /* Number of bytes in zTerm */
195: int nMalloc; /* Size of malloc'd buffer at zMalloc */
196: char *zMalloc; /* Malloc'd space (possibly) used for zTerm */
197: int nData; /* Bytes of valid data so far */
198: char *aData; /* Node data */
199: };
200:
201: /*
202: ** Valid values for the second argument to fts3SqlStmt().
203: */
204: #define SQL_DELETE_CONTENT 0
205: #define SQL_IS_EMPTY 1
206: #define SQL_DELETE_ALL_CONTENT 2
207: #define SQL_DELETE_ALL_SEGMENTS 3
208: #define SQL_DELETE_ALL_SEGDIR 4
209: #define SQL_DELETE_ALL_DOCSIZE 5
210: #define SQL_DELETE_ALL_STAT 6
211: #define SQL_SELECT_CONTENT_BY_ROWID 7
212: #define SQL_NEXT_SEGMENT_INDEX 8
213: #define SQL_INSERT_SEGMENTS 9
214: #define SQL_NEXT_SEGMENTS_ID 10
215: #define SQL_INSERT_SEGDIR 11
216: #define SQL_SELECT_LEVEL 12
217: #define SQL_SELECT_LEVEL_RANGE 13
218: #define SQL_SELECT_LEVEL_COUNT 14
219: #define SQL_SELECT_SEGDIR_MAX_LEVEL 15
220: #define SQL_DELETE_SEGDIR_LEVEL 16
221: #define SQL_DELETE_SEGMENTS_RANGE 17
222: #define SQL_CONTENT_INSERT 18
223: #define SQL_DELETE_DOCSIZE 19
224: #define SQL_REPLACE_DOCSIZE 20
225: #define SQL_SELECT_DOCSIZE 21
226: #define SQL_SELECT_DOCTOTAL 22
227: #define SQL_REPLACE_DOCTOTAL 23
228:
229: #define SQL_SELECT_ALL_PREFIX_LEVEL 24
230: #define SQL_DELETE_ALL_TERMS_SEGDIR 25
231:
232: #define SQL_DELETE_SEGDIR_RANGE 26
233:
234: /*
235: ** This function is used to obtain an SQLite prepared statement handle
236: ** for the statement identified by the second argument. If successful,
237: ** *pp is set to the requested statement handle and SQLITE_OK returned.
238: ** Otherwise, an SQLite error code is returned and *pp is set to 0.
239: **
240: ** If argument apVal is not NULL, then it must point to an array with
241: ** at least as many entries as the requested statement has bound
242: ** parameters. The values are bound to the statements parameters before
243: ** returning.
244: */
245: static int fts3SqlStmt(
246: Fts3Table *p, /* Virtual table handle */
247: int eStmt, /* One of the SQL_XXX constants above */
248: sqlite3_stmt **pp, /* OUT: Statement handle */
249: sqlite3_value **apVal /* Values to bind to statement */
250: ){
251: const char *azSql[] = {
252: /* 0 */ "DELETE FROM %Q.'%q_content' WHERE rowid = ?",
253: /* 1 */ "SELECT NOT EXISTS(SELECT docid FROM %Q.'%q_content' WHERE rowid!=?)",
254: /* 2 */ "DELETE FROM %Q.'%q_content'",
255: /* 3 */ "DELETE FROM %Q.'%q_segments'",
256: /* 4 */ "DELETE FROM %Q.'%q_segdir'",
257: /* 5 */ "DELETE FROM %Q.'%q_docsize'",
258: /* 6 */ "DELETE FROM %Q.'%q_stat'",
259: /* 7 */ "SELECT %s WHERE rowid=?",
260: /* 8 */ "SELECT (SELECT max(idx) FROM %Q.'%q_segdir' WHERE level = ?) + 1",
261: /* 9 */ "INSERT INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)",
262: /* 10 */ "SELECT coalesce((SELECT max(blockid) FROM %Q.'%q_segments') + 1, 1)",
263: /* 11 */ "INSERT INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)",
264:
265: /* Return segments in order from oldest to newest.*/
266: /* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
267: "FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC",
268: /* 13 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
269: "FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?"
270: "ORDER BY level DESC, idx ASC",
271:
272: /* 14 */ "SELECT count(*) FROM %Q.'%q_segdir' WHERE level = ?",
273: /* 15 */ "SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?",
274:
275: /* 16 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ?",
276: /* 17 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?",
277: /* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%s)",
278: /* 19 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?",
279: /* 20 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)",
280: /* 21 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?",
281: /* 22 */ "SELECT value FROM %Q.'%q_stat' WHERE id=0",
282: /* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(0,?)",
283: /* 24 */ "",
284: /* 25 */ "",
285:
286: /* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?",
287:
288: };
289: int rc = SQLITE_OK;
290: sqlite3_stmt *pStmt;
291:
292: assert( SizeofArray(azSql)==SizeofArray(p->aStmt) );
293: assert( eStmt<SizeofArray(azSql) && eStmt>=0 );
294:
295: pStmt = p->aStmt[eStmt];
296: if( !pStmt ){
297: char *zSql;
298: if( eStmt==SQL_CONTENT_INSERT ){
299: zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName, p->zWriteExprlist);
300: }else if( eStmt==SQL_SELECT_CONTENT_BY_ROWID ){
301: zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist);
302: }else{
303: zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName);
304: }
305: if( !zSql ){
306: rc = SQLITE_NOMEM;
307: }else{
308: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, NULL);
309: sqlite3_free(zSql);
310: assert( rc==SQLITE_OK || pStmt==0 );
311: p->aStmt[eStmt] = pStmt;
312: }
313: }
314: if( apVal ){
315: int i;
316: int nParam = sqlite3_bind_parameter_count(pStmt);
317: for(i=0; rc==SQLITE_OK && i<nParam; i++){
318: rc = sqlite3_bind_value(pStmt, i+1, apVal[i]);
319: }
320: }
321: *pp = pStmt;
322: return rc;
323: }
324:
325: static int fts3SelectDocsize(
326: Fts3Table *pTab, /* FTS3 table handle */
327: int eStmt, /* Either SQL_SELECT_DOCSIZE or DOCTOTAL */
328: sqlite3_int64 iDocid, /* Docid to bind for SQL_SELECT_DOCSIZE */
329: sqlite3_stmt **ppStmt /* OUT: Statement handle */
330: ){
331: sqlite3_stmt *pStmt = 0; /* Statement requested from fts3SqlStmt() */
332: int rc; /* Return code */
333:
334: assert( eStmt==SQL_SELECT_DOCSIZE || eStmt==SQL_SELECT_DOCTOTAL );
335:
336: rc = fts3SqlStmt(pTab, eStmt, &pStmt, 0);
337: if( rc==SQLITE_OK ){
338: if( eStmt==SQL_SELECT_DOCSIZE ){
339: sqlite3_bind_int64(pStmt, 1, iDocid);
340: }
341: rc = sqlite3_step(pStmt);
342: if( rc!=SQLITE_ROW || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){
343: rc = sqlite3_reset(pStmt);
344: if( rc==SQLITE_OK ) rc = FTS_CORRUPT_VTAB;
345: pStmt = 0;
346: }else{
347: rc = SQLITE_OK;
348: }
349: }
350:
351: *ppStmt = pStmt;
352: return rc;
353: }
354:
355: int sqlite3Fts3SelectDoctotal(
356: Fts3Table *pTab, /* Fts3 table handle */
357: sqlite3_stmt **ppStmt /* OUT: Statement handle */
358: ){
359: return fts3SelectDocsize(pTab, SQL_SELECT_DOCTOTAL, 0, ppStmt);
360: }
361:
362: int sqlite3Fts3SelectDocsize(
363: Fts3Table *pTab, /* Fts3 table handle */
364: sqlite3_int64 iDocid, /* Docid to read size data for */
365: sqlite3_stmt **ppStmt /* OUT: Statement handle */
366: ){
367: return fts3SelectDocsize(pTab, SQL_SELECT_DOCSIZE, iDocid, ppStmt);
368: }
369:
370: /*
371: ** Similar to fts3SqlStmt(). Except, after binding the parameters in
372: ** array apVal[] to the SQL statement identified by eStmt, the statement
373: ** is executed.
374: **
375: ** Returns SQLITE_OK if the statement is successfully executed, or an
376: ** SQLite error code otherwise.
377: */
378: static void fts3SqlExec(
379: int *pRC, /* Result code */
380: Fts3Table *p, /* The FTS3 table */
381: int eStmt, /* Index of statement to evaluate */
382: sqlite3_value **apVal /* Parameters to bind */
383: ){
384: sqlite3_stmt *pStmt;
385: int rc;
386: if( *pRC ) return;
387: rc = fts3SqlStmt(p, eStmt, &pStmt, apVal);
388: if( rc==SQLITE_OK ){
389: sqlite3_step(pStmt);
390: rc = sqlite3_reset(pStmt);
391: }
392: *pRC = rc;
393: }
394:
395:
396: /*
397: ** This function ensures that the caller has obtained a shared-cache
398: ** table-lock on the %_content table. This is required before reading
399: ** data from the fts3 table. If this lock is not acquired first, then
400: ** the caller may end up holding read-locks on the %_segments and %_segdir
401: ** tables, but no read-lock on the %_content table. If this happens
402: ** a second connection will be able to write to the fts3 table, but
403: ** attempting to commit those writes might return SQLITE_LOCKED or
404: ** SQLITE_LOCKED_SHAREDCACHE (because the commit attempts to obtain
405: ** write-locks on the %_segments and %_segdir ** tables).
406: **
407: ** We try to avoid this because if FTS3 returns any error when committing
408: ** a transaction, the whole transaction will be rolled back. And this is
409: ** not what users expect when they get SQLITE_LOCKED_SHAREDCACHE. It can
410: ** still happen if the user reads data directly from the %_segments or
411: ** %_segdir tables instead of going through FTS3 though.
412: **
413: ** This reasoning does not apply to a content=xxx table.
414: */
415: int sqlite3Fts3ReadLock(Fts3Table *p){
416: int rc; /* Return code */
417: sqlite3_stmt *pStmt; /* Statement used to obtain lock */
418:
419: if( p->zContentTbl==0 ){
420: rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pStmt, 0);
421: if( rc==SQLITE_OK ){
422: sqlite3_bind_null(pStmt, 1);
423: sqlite3_step(pStmt);
424: rc = sqlite3_reset(pStmt);
425: }
426: }else{
427: rc = SQLITE_OK;
428: }
429:
430: return rc;
431: }
432:
433: /*
434: ** Set *ppStmt to a statement handle that may be used to iterate through
435: ** all rows in the %_segdir table, from oldest to newest. If successful,
436: ** return SQLITE_OK. If an error occurs while preparing the statement,
437: ** return an SQLite error code.
438: **
439: ** There is only ever one instance of this SQL statement compiled for
440: ** each FTS3 table.
441: **
442: ** The statement returns the following columns from the %_segdir table:
443: **
444: ** 0: idx
445: ** 1: start_block
446: ** 2: leaves_end_block
447: ** 3: end_block
448: ** 4: root
449: */
450: int sqlite3Fts3AllSegdirs(
451: Fts3Table *p, /* FTS3 table */
452: int iIndex, /* Index for p->aIndex[] */
453: int iLevel, /* Level to select */
454: sqlite3_stmt **ppStmt /* OUT: Compiled statement */
455: ){
456: int rc;
457: sqlite3_stmt *pStmt = 0;
458:
459: assert( iLevel==FTS3_SEGCURSOR_ALL || iLevel>=0 );
460: assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
461: assert( iIndex>=0 && iIndex<p->nIndex );
462:
463: if( iLevel<0 ){
464: /* "SELECT * FROM %_segdir WHERE level BETWEEN ? AND ? ORDER BY ..." */
465: rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE, &pStmt, 0);
466: if( rc==SQLITE_OK ){
467: sqlite3_bind_int(pStmt, 1, iIndex*FTS3_SEGDIR_MAXLEVEL);
468: sqlite3_bind_int(pStmt, 2, (iIndex+1)*FTS3_SEGDIR_MAXLEVEL-1);
469: }
470: }else{
471: /* "SELECT * FROM %_segdir WHERE level = ? ORDER BY ..." */
472: rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0);
473: if( rc==SQLITE_OK ){
474: sqlite3_bind_int(pStmt, 1, iLevel+iIndex*FTS3_SEGDIR_MAXLEVEL);
475: }
476: }
477: *ppStmt = pStmt;
478: return rc;
479: }
480:
481:
482: /*
483: ** Append a single varint to a PendingList buffer. SQLITE_OK is returned
484: ** if successful, or an SQLite error code otherwise.
485: **
486: ** This function also serves to allocate the PendingList structure itself.
487: ** For example, to create a new PendingList structure containing two
488: ** varints:
489: **
490: ** PendingList *p = 0;
491: ** fts3PendingListAppendVarint(&p, 1);
492: ** fts3PendingListAppendVarint(&p, 2);
493: */
494: static int fts3PendingListAppendVarint(
495: PendingList **pp, /* IN/OUT: Pointer to PendingList struct */
496: sqlite3_int64 i /* Value to append to data */
497: ){
498: PendingList *p = *pp;
499:
500: /* Allocate or grow the PendingList as required. */
501: if( !p ){
502: p = sqlite3_malloc(sizeof(*p) + 100);
503: if( !p ){
504: return SQLITE_NOMEM;
505: }
506: p->nSpace = 100;
507: p->aData = (char *)&p[1];
508: p->nData = 0;
509: }
510: else if( p->nData+FTS3_VARINT_MAX+1>p->nSpace ){
511: int nNew = p->nSpace * 2;
512: p = sqlite3_realloc(p, sizeof(*p) + nNew);
513: if( !p ){
514: sqlite3_free(*pp);
515: *pp = 0;
516: return SQLITE_NOMEM;
517: }
518: p->nSpace = nNew;
519: p->aData = (char *)&p[1];
520: }
521:
522: /* Append the new serialized varint to the end of the list. */
523: p->nData += sqlite3Fts3PutVarint(&p->aData[p->nData], i);
524: p->aData[p->nData] = '\0';
525: *pp = p;
526: return SQLITE_OK;
527: }
528:
529: /*
530: ** Add a docid/column/position entry to a PendingList structure. Non-zero
531: ** is returned if the structure is sqlite3_realloced as part of adding
532: ** the entry. Otherwise, zero.
533: **
534: ** If an OOM error occurs, *pRc is set to SQLITE_NOMEM before returning.
535: ** Zero is always returned in this case. Otherwise, if no OOM error occurs,
536: ** it is set to SQLITE_OK.
537: */
538: static int fts3PendingListAppend(
539: PendingList **pp, /* IN/OUT: PendingList structure */
540: sqlite3_int64 iDocid, /* Docid for entry to add */
541: sqlite3_int64 iCol, /* Column for entry to add */
542: sqlite3_int64 iPos, /* Position of term for entry to add */
543: int *pRc /* OUT: Return code */
544: ){
545: PendingList *p = *pp;
546: int rc = SQLITE_OK;
547:
548: assert( !p || p->iLastDocid<=iDocid );
549:
550: if( !p || p->iLastDocid!=iDocid ){
551: sqlite3_int64 iDelta = iDocid - (p ? p->iLastDocid : 0);
552: if( p ){
553: assert( p->nData<p->nSpace );
554: assert( p->aData[p->nData]==0 );
555: p->nData++;
556: }
557: if( SQLITE_OK!=(rc = fts3PendingListAppendVarint(&p, iDelta)) ){
558: goto pendinglistappend_out;
559: }
560: p->iLastCol = -1;
561: p->iLastPos = 0;
562: p->iLastDocid = iDocid;
563: }
564: if( iCol>0 && p->iLastCol!=iCol ){
565: if( SQLITE_OK!=(rc = fts3PendingListAppendVarint(&p, 1))
566: || SQLITE_OK!=(rc = fts3PendingListAppendVarint(&p, iCol))
567: ){
568: goto pendinglistappend_out;
569: }
570: p->iLastCol = iCol;
571: p->iLastPos = 0;
572: }
573: if( iCol>=0 ){
574: assert( iPos>p->iLastPos || (iPos==0 && p->iLastPos==0) );
575: rc = fts3PendingListAppendVarint(&p, 2+iPos-p->iLastPos);
576: if( rc==SQLITE_OK ){
577: p->iLastPos = iPos;
578: }
579: }
580:
581: pendinglistappend_out:
582: *pRc = rc;
583: if( p!=*pp ){
584: *pp = p;
585: return 1;
586: }
587: return 0;
588: }
589:
590: /*
591: ** Free a PendingList object allocated by fts3PendingListAppend().
592: */
593: static void fts3PendingListDelete(PendingList *pList){
594: sqlite3_free(pList);
595: }
596:
597: /*
598: ** Add an entry to one of the pending-terms hash tables.
599: */
600: static int fts3PendingTermsAddOne(
601: Fts3Table *p,
602: int iCol,
603: int iPos,
604: Fts3Hash *pHash, /* Pending terms hash table to add entry to */
605: const char *zToken,
606: int nToken
607: ){
608: PendingList *pList;
609: int rc = SQLITE_OK;
610:
611: pList = (PendingList *)fts3HashFind(pHash, zToken, nToken);
612: if( pList ){
613: p->nPendingData -= (pList->nData + nToken + sizeof(Fts3HashElem));
614: }
615: if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){
616: if( pList==fts3HashInsert(pHash, zToken, nToken, pList) ){
617: /* Malloc failed while inserting the new entry. This can only
618: ** happen if there was no previous entry for this token.
619: */
620: assert( 0==fts3HashFind(pHash, zToken, nToken) );
621: sqlite3_free(pList);
622: rc = SQLITE_NOMEM;
623: }
624: }
625: if( rc==SQLITE_OK ){
626: p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem));
627: }
628: return rc;
629: }
630:
631: /*
632: ** Tokenize the nul-terminated string zText and add all tokens to the
633: ** pending-terms hash-table. The docid used is that currently stored in
634: ** p->iPrevDocid, and the column is specified by argument iCol.
635: **
636: ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code.
637: */
638: static int fts3PendingTermsAdd(
639: Fts3Table *p, /* Table into which text will be inserted */
640: const char *zText, /* Text of document to be inserted */
641: int iCol, /* Column into which text is being inserted */
642: u32 *pnWord /* OUT: Number of tokens inserted */
643: ){
644: int rc;
645: int iStart;
646: int iEnd;
647: int iPos;
648: int nWord = 0;
649:
650: char const *zToken;
651: int nToken;
652:
653: sqlite3_tokenizer *pTokenizer = p->pTokenizer;
654: sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
655: sqlite3_tokenizer_cursor *pCsr;
656: int (*xNext)(sqlite3_tokenizer_cursor *pCursor,
657: const char**,int*,int*,int*,int*);
658:
659: assert( pTokenizer && pModule );
660:
661: /* If the user has inserted a NULL value, this function may be called with
662: ** zText==0. In this case, add zero token entries to the hash table and
663: ** return early. */
664: if( zText==0 ){
665: *pnWord = 0;
666: return SQLITE_OK;
667: }
668:
669: rc = pModule->xOpen(pTokenizer, zText, -1, &pCsr);
670: if( rc!=SQLITE_OK ){
671: return rc;
672: }
673: pCsr->pTokenizer = pTokenizer;
674:
675: xNext = pModule->xNext;
676: while( SQLITE_OK==rc
677: && SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos))
678: ){
679: int i;
680: if( iPos>=nWord ) nWord = iPos+1;
681:
682: /* Positions cannot be negative; we use -1 as a terminator internally.
683: ** Tokens must have a non-zero length.
684: */
685: if( iPos<0 || !zToken || nToken<=0 ){
686: rc = SQLITE_ERROR;
687: break;
688: }
689:
690: /* Add the term to the terms index */
691: rc = fts3PendingTermsAddOne(
692: p, iCol, iPos, &p->aIndex[0].hPending, zToken, nToken
693: );
694:
695: /* Add the term to each of the prefix indexes that it is not too
696: ** short for. */
697: for(i=1; rc==SQLITE_OK && i<p->nIndex; i++){
698: struct Fts3Index *pIndex = &p->aIndex[i];
699: if( nToken<pIndex->nPrefix ) continue;
700: rc = fts3PendingTermsAddOne(
701: p, iCol, iPos, &pIndex->hPending, zToken, pIndex->nPrefix
702: );
703: }
704: }
705:
706: pModule->xClose(pCsr);
707: *pnWord = nWord;
708: return (rc==SQLITE_DONE ? SQLITE_OK : rc);
709: }
710:
711: /*
712: ** Calling this function indicates that subsequent calls to
713: ** fts3PendingTermsAdd() are to add term/position-list pairs for the
714: ** contents of the document with docid iDocid.
715: */
716: static int fts3PendingTermsDocid(Fts3Table *p, sqlite_int64 iDocid){
717: /* TODO(shess) Explore whether partially flushing the buffer on
718: ** forced-flush would provide better performance. I suspect that if
719: ** we ordered the doclists by size and flushed the largest until the
720: ** buffer was half empty, that would let the less frequent terms
721: ** generate longer doclists.
722: */
723: if( iDocid<=p->iPrevDocid || p->nPendingData>p->nMaxPendingData ){
724: int rc = sqlite3Fts3PendingTermsFlush(p);
725: if( rc!=SQLITE_OK ) return rc;
726: }
727: p->iPrevDocid = iDocid;
728: return SQLITE_OK;
729: }
730:
731: /*
732: ** Discard the contents of the pending-terms hash tables.
733: */
734: void sqlite3Fts3PendingTermsClear(Fts3Table *p){
735: int i;
736: for(i=0; i<p->nIndex; i++){
737: Fts3HashElem *pElem;
738: Fts3Hash *pHash = &p->aIndex[i].hPending;
739: for(pElem=fts3HashFirst(pHash); pElem; pElem=fts3HashNext(pElem)){
740: PendingList *pList = (PendingList *)fts3HashData(pElem);
741: fts3PendingListDelete(pList);
742: }
743: fts3HashClear(pHash);
744: }
745: p->nPendingData = 0;
746: }
747:
748: /*
749: ** This function is called by the xUpdate() method as part of an INSERT
750: ** operation. It adds entries for each term in the new record to the
751: ** pendingTerms hash table.
752: **
753: ** Argument apVal is the same as the similarly named argument passed to
754: ** fts3InsertData(). Parameter iDocid is the docid of the new row.
755: */
756: static int fts3InsertTerms(Fts3Table *p, sqlite3_value **apVal, u32 *aSz){
757: int i; /* Iterator variable */
758: for(i=2; i<p->nColumn+2; i++){
759: const char *zText = (const char *)sqlite3_value_text(apVal[i]);
760: int rc = fts3PendingTermsAdd(p, zText, i-2, &aSz[i-2]);
761: if( rc!=SQLITE_OK ){
762: return rc;
763: }
764: aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]);
765: }
766: return SQLITE_OK;
767: }
768:
769: /*
770: ** This function is called by the xUpdate() method for an INSERT operation.
771: ** The apVal parameter is passed a copy of the apVal argument passed by
772: ** SQLite to the xUpdate() method. i.e:
773: **
774: ** apVal[0] Not used for INSERT.
775: ** apVal[1] rowid
776: ** apVal[2] Left-most user-defined column
777: ** ...
778: ** apVal[p->nColumn+1] Right-most user-defined column
779: ** apVal[p->nColumn+2] Hidden column with same name as table
780: ** apVal[p->nColumn+3] Hidden "docid" column (alias for rowid)
781: */
782: static int fts3InsertData(
783: Fts3Table *p, /* Full-text table */
784: sqlite3_value **apVal, /* Array of values to insert */
785: sqlite3_int64 *piDocid /* OUT: Docid for row just inserted */
786: ){
787: int rc; /* Return code */
788: sqlite3_stmt *pContentInsert; /* INSERT INTO %_content VALUES(...) */
789:
790: if( p->zContentTbl ){
791: sqlite3_value *pRowid = apVal[p->nColumn+3];
792: if( sqlite3_value_type(pRowid)==SQLITE_NULL ){
793: pRowid = apVal[1];
794: }
795: if( sqlite3_value_type(pRowid)!=SQLITE_INTEGER ){
796: return SQLITE_CONSTRAINT;
797: }
798: *piDocid = sqlite3_value_int64(pRowid);
799: return SQLITE_OK;
800: }
801:
802: /* Locate the statement handle used to insert data into the %_content
803: ** table. The SQL for this statement is:
804: **
805: ** INSERT INTO %_content VALUES(?, ?, ?, ...)
806: **
807: ** The statement features N '?' variables, where N is the number of user
808: ** defined columns in the FTS3 table, plus one for the docid field.
809: */
810: rc = fts3SqlStmt(p, SQL_CONTENT_INSERT, &pContentInsert, &apVal[1]);
811: if( rc!=SQLITE_OK ){
812: return rc;
813: }
814:
815: /* There is a quirk here. The users INSERT statement may have specified
816: ** a value for the "rowid" field, for the "docid" field, or for both.
817: ** Which is a problem, since "rowid" and "docid" are aliases for the
818: ** same value. For example:
819: **
820: ** INSERT INTO fts3tbl(rowid, docid) VALUES(1, 2);
821: **
822: ** In FTS3, this is an error. It is an error to specify non-NULL values
823: ** for both docid and some other rowid alias.
824: */
825: if( SQLITE_NULL!=sqlite3_value_type(apVal[3+p->nColumn]) ){
826: if( SQLITE_NULL==sqlite3_value_type(apVal[0])
827: && SQLITE_NULL!=sqlite3_value_type(apVal[1])
828: ){
829: /* A rowid/docid conflict. */
830: return SQLITE_ERROR;
831: }
832: rc = sqlite3_bind_value(pContentInsert, 1, apVal[3+p->nColumn]);
833: if( rc!=SQLITE_OK ) return rc;
834: }
835:
836: /* Execute the statement to insert the record. Set *piDocid to the
837: ** new docid value.
838: */
839: sqlite3_step(pContentInsert);
840: rc = sqlite3_reset(pContentInsert);
841:
842: *piDocid = sqlite3_last_insert_rowid(p->db);
843: return rc;
844: }
845:
846:
847:
848: /*
849: ** Remove all data from the FTS3 table. Clear the hash table containing
850: ** pending terms.
851: */
852: static int fts3DeleteAll(Fts3Table *p, int bContent){
853: int rc = SQLITE_OK; /* Return code */
854:
855: /* Discard the contents of the pending-terms hash table. */
856: sqlite3Fts3PendingTermsClear(p);
857:
858: /* Delete everything from the shadow tables. Except, leave %_content as
859: ** is if bContent is false. */
860: assert( p->zContentTbl==0 || bContent==0 );
861: if( bContent ) fts3SqlExec(&rc, p, SQL_DELETE_ALL_CONTENT, 0);
862: fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGMENTS, 0);
863: fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0);
864: if( p->bHasDocsize ){
865: fts3SqlExec(&rc, p, SQL_DELETE_ALL_DOCSIZE, 0);
866: }
867: if( p->bHasStat ){
868: fts3SqlExec(&rc, p, SQL_DELETE_ALL_STAT, 0);
869: }
870: return rc;
871: }
872:
873: /*
874: ** The first element in the apVal[] array is assumed to contain the docid
875: ** (an integer) of a row about to be deleted. Remove all terms from the
876: ** full-text index.
877: */
878: static void fts3DeleteTerms(
879: int *pRC, /* Result code */
880: Fts3Table *p, /* The FTS table to delete from */
881: sqlite3_value *pRowid, /* The docid to be deleted */
882: u32 *aSz /* Sizes of deleted document written here */
883: ){
884: int rc;
885: sqlite3_stmt *pSelect;
886:
887: if( *pRC ) return;
888: rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid);
889: if( rc==SQLITE_OK ){
890: if( SQLITE_ROW==sqlite3_step(pSelect) ){
891: int i;
892: for(i=1; i<=p->nColumn; i++){
893: const char *zText = (const char *)sqlite3_column_text(pSelect, i);
894: rc = fts3PendingTermsAdd(p, zText, -1, &aSz[i-1]);
895: if( rc!=SQLITE_OK ){
896: sqlite3_reset(pSelect);
897: *pRC = rc;
898: return;
899: }
900: aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i);
901: }
902: }
903: rc = sqlite3_reset(pSelect);
904: }else{
905: sqlite3_reset(pSelect);
906: }
907: *pRC = rc;
908: }
909:
910: /*
911: ** Forward declaration to account for the circular dependency between
912: ** functions fts3SegmentMerge() and fts3AllocateSegdirIdx().
913: */
914: static int fts3SegmentMerge(Fts3Table *, int, int);
915:
916: /*
917: ** This function allocates a new level iLevel index in the segdir table.
918: ** Usually, indexes are allocated within a level sequentially starting
919: ** with 0, so the allocated index is one greater than the value returned
920: ** by:
921: **
922: ** SELECT max(idx) FROM %_segdir WHERE level = :iLevel
923: **
924: ** However, if there are already FTS3_MERGE_COUNT indexes at the requested
925: ** level, they are merged into a single level (iLevel+1) segment and the
926: ** allocated index is 0.
927: **
928: ** If successful, *piIdx is set to the allocated index slot and SQLITE_OK
929: ** returned. Otherwise, an SQLite error code is returned.
930: */
931: static int fts3AllocateSegdirIdx(
932: Fts3Table *p,
933: int iIndex, /* Index for p->aIndex */
934: int iLevel,
935: int *piIdx
936: ){
937: int rc; /* Return Code */
938: sqlite3_stmt *pNextIdx; /* Query for next idx at level iLevel */
939: int iNext = 0; /* Result of query pNextIdx */
940:
941: /* Set variable iNext to the next available segdir index at level iLevel. */
942: rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pNextIdx, 0);
943: if( rc==SQLITE_OK ){
944: sqlite3_bind_int(pNextIdx, 1, iIndex*FTS3_SEGDIR_MAXLEVEL + iLevel);
945: if( SQLITE_ROW==sqlite3_step(pNextIdx) ){
946: iNext = sqlite3_column_int(pNextIdx, 0);
947: }
948: rc = sqlite3_reset(pNextIdx);
949: }
950:
951: if( rc==SQLITE_OK ){
952: /* If iNext is FTS3_MERGE_COUNT, indicating that level iLevel is already
953: ** full, merge all segments in level iLevel into a single iLevel+1
954: ** segment and allocate (newly freed) index 0 at level iLevel. Otherwise,
955: ** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext.
956: */
957: if( iNext>=FTS3_MERGE_COUNT ){
958: rc = fts3SegmentMerge(p, iIndex, iLevel);
959: *piIdx = 0;
960: }else{
961: *piIdx = iNext;
962: }
963: }
964:
965: return rc;
966: }
967:
968: /*
969: ** The %_segments table is declared as follows:
970: **
971: ** CREATE TABLE %_segments(blockid INTEGER PRIMARY KEY, block BLOB)
972: **
973: ** This function reads data from a single row of the %_segments table. The
974: ** specific row is identified by the iBlockid parameter. If paBlob is not
975: ** NULL, then a buffer is allocated using sqlite3_malloc() and populated
976: ** with the contents of the blob stored in the "block" column of the
977: ** identified table row is. Whether or not paBlob is NULL, *pnBlob is set
978: ** to the size of the blob in bytes before returning.
979: **
980: ** If an error occurs, or the table does not contain the specified row,
981: ** an SQLite error code is returned. Otherwise, SQLITE_OK is returned. If
982: ** paBlob is non-NULL, then it is the responsibility of the caller to
983: ** eventually free the returned buffer.
984: **
985: ** This function may leave an open sqlite3_blob* handle in the
986: ** Fts3Table.pSegments variable. This handle is reused by subsequent calls
987: ** to this function. The handle may be closed by calling the
988: ** sqlite3Fts3SegmentsClose() function. Reusing a blob handle is a handy
989: ** performance improvement, but the blob handle should always be closed
990: ** before control is returned to the user (to prevent a lock being held
991: ** on the database file for longer than necessary). Thus, any virtual table
992: ** method (xFilter etc.) that may directly or indirectly call this function
993: ** must call sqlite3Fts3SegmentsClose() before returning.
994: */
995: int sqlite3Fts3ReadBlock(
996: Fts3Table *p, /* FTS3 table handle */
997: sqlite3_int64 iBlockid, /* Access the row with blockid=$iBlockid */
998: char **paBlob, /* OUT: Blob data in malloc'd buffer */
999: int *pnBlob, /* OUT: Size of blob data */
1000: int *pnLoad /* OUT: Bytes actually loaded */
1001: ){
1002: int rc; /* Return code */
1003:
1004: /* pnBlob must be non-NULL. paBlob may be NULL or non-NULL. */
1005: assert( pnBlob);
1006:
1007: if( p->pSegments ){
1008: rc = sqlite3_blob_reopen(p->pSegments, iBlockid);
1009: }else{
1010: if( 0==p->zSegmentsTbl ){
1011: p->zSegmentsTbl = sqlite3_mprintf("%s_segments", p->zName);
1012: if( 0==p->zSegmentsTbl ) return SQLITE_NOMEM;
1013: }
1014: rc = sqlite3_blob_open(
1015: p->db, p->zDb, p->zSegmentsTbl, "block", iBlockid, 0, &p->pSegments
1016: );
1017: }
1018:
1019: if( rc==SQLITE_OK ){
1020: int nByte = sqlite3_blob_bytes(p->pSegments);
1021: *pnBlob = nByte;
1022: if( paBlob ){
1023: char *aByte = sqlite3_malloc(nByte + FTS3_NODE_PADDING);
1024: if( !aByte ){
1025: rc = SQLITE_NOMEM;
1026: }else{
1027: if( pnLoad && nByte>(FTS3_NODE_CHUNK_THRESHOLD) ){
1028: nByte = FTS3_NODE_CHUNKSIZE;
1029: *pnLoad = nByte;
1030: }
1031: rc = sqlite3_blob_read(p->pSegments, aByte, nByte, 0);
1032: memset(&aByte[nByte], 0, FTS3_NODE_PADDING);
1033: if( rc!=SQLITE_OK ){
1034: sqlite3_free(aByte);
1035: aByte = 0;
1036: }
1037: }
1038: *paBlob = aByte;
1039: }
1040: }
1041:
1042: return rc;
1043: }
1044:
1045: /*
1046: ** Close the blob handle at p->pSegments, if it is open. See comments above
1047: ** the sqlite3Fts3ReadBlock() function for details.
1048: */
1049: void sqlite3Fts3SegmentsClose(Fts3Table *p){
1050: sqlite3_blob_close(p->pSegments);
1051: p->pSegments = 0;
1052: }
1053:
1054: static int fts3SegReaderIncrRead(Fts3SegReader *pReader){
1055: int nRead; /* Number of bytes to read */
1056: int rc; /* Return code */
1057:
1058: nRead = MIN(pReader->nNode - pReader->nPopulate, FTS3_NODE_CHUNKSIZE);
1059: rc = sqlite3_blob_read(
1060: pReader->pBlob,
1061: &pReader->aNode[pReader->nPopulate],
1062: nRead,
1063: pReader->nPopulate
1064: );
1065:
1066: if( rc==SQLITE_OK ){
1067: pReader->nPopulate += nRead;
1068: memset(&pReader->aNode[pReader->nPopulate], 0, FTS3_NODE_PADDING);
1069: if( pReader->nPopulate==pReader->nNode ){
1070: sqlite3_blob_close(pReader->pBlob);
1071: pReader->pBlob = 0;
1072: pReader->nPopulate = 0;
1073: }
1074: }
1075: return rc;
1076: }
1077:
1078: static int fts3SegReaderRequire(Fts3SegReader *pReader, char *pFrom, int nByte){
1079: int rc = SQLITE_OK;
1080: assert( !pReader->pBlob
1081: || (pFrom>=pReader->aNode && pFrom<&pReader->aNode[pReader->nNode])
1082: );
1083: while( pReader->pBlob && rc==SQLITE_OK
1084: && (pFrom - pReader->aNode + nByte)>pReader->nPopulate
1085: ){
1086: rc = fts3SegReaderIncrRead(pReader);
1087: }
1088: return rc;
1089: }
1090:
1091: /*
1092: ** Move the iterator passed as the first argument to the next term in the
1093: ** segment. If successful, SQLITE_OK is returned. If there is no next term,
1094: ** SQLITE_DONE. Otherwise, an SQLite error code.
1095: */
1096: static int fts3SegReaderNext(
1097: Fts3Table *p,
1098: Fts3SegReader *pReader,
1099: int bIncr
1100: ){
1101: int rc; /* Return code of various sub-routines */
1102: char *pNext; /* Cursor variable */
1103: int nPrefix; /* Number of bytes in term prefix */
1104: int nSuffix; /* Number of bytes in term suffix */
1105:
1106: if( !pReader->aDoclist ){
1107: pNext = pReader->aNode;
1108: }else{
1109: pNext = &pReader->aDoclist[pReader->nDoclist];
1110: }
1111:
1112: if( !pNext || pNext>=&pReader->aNode[pReader->nNode] ){
1113:
1114: if( fts3SegReaderIsPending(pReader) ){
1115: Fts3HashElem *pElem = *(pReader->ppNextElem);
1116: if( pElem==0 ){
1117: pReader->aNode = 0;
1118: }else{
1119: PendingList *pList = (PendingList *)fts3HashData(pElem);
1120: pReader->zTerm = (char *)fts3HashKey(pElem);
1121: pReader->nTerm = fts3HashKeysize(pElem);
1122: pReader->nNode = pReader->nDoclist = pList->nData + 1;
1123: pReader->aNode = pReader->aDoclist = pList->aData;
1124: pReader->ppNextElem++;
1125: assert( pReader->aNode );
1126: }
1127: return SQLITE_OK;
1128: }
1129:
1130: if( !fts3SegReaderIsRootOnly(pReader) ){
1131: sqlite3_free(pReader->aNode);
1132: sqlite3_blob_close(pReader->pBlob);
1133: pReader->pBlob = 0;
1134: }
1135: pReader->aNode = 0;
1136:
1137: /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf
1138: ** blocks have already been traversed. */
1139: assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock );
1140: if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){
1141: return SQLITE_OK;
1142: }
1143:
1144: rc = sqlite3Fts3ReadBlock(
1145: p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode,
1146: (bIncr ? &pReader->nPopulate : 0)
1147: );
1148: if( rc!=SQLITE_OK ) return rc;
1149: assert( pReader->pBlob==0 );
1150: if( bIncr && pReader->nPopulate<pReader->nNode ){
1151: pReader->pBlob = p->pSegments;
1152: p->pSegments = 0;
1153: }
1154: pNext = pReader->aNode;
1155: }
1156:
1157: assert( !fts3SegReaderIsPending(pReader) );
1158:
1159: rc = fts3SegReaderRequire(pReader, pNext, FTS3_VARINT_MAX*2);
1160: if( rc!=SQLITE_OK ) return rc;
1161:
1162: /* Because of the FTS3_NODE_PADDING bytes of padding, the following is
1163: ** safe (no risk of overread) even if the node data is corrupted. */
1164: pNext += sqlite3Fts3GetVarint32(pNext, &nPrefix);
1165: pNext += sqlite3Fts3GetVarint32(pNext, &nSuffix);
1166: if( nPrefix<0 || nSuffix<=0
1167: || &pNext[nSuffix]>&pReader->aNode[pReader->nNode]
1168: ){
1169: return FTS_CORRUPT_VTAB;
1170: }
1171:
1172: if( nPrefix+nSuffix>pReader->nTermAlloc ){
1173: int nNew = (nPrefix+nSuffix)*2;
1174: char *zNew = sqlite3_realloc(pReader->zTerm, nNew);
1175: if( !zNew ){
1176: return SQLITE_NOMEM;
1177: }
1178: pReader->zTerm = zNew;
1179: pReader->nTermAlloc = nNew;
1180: }
1181:
1182: rc = fts3SegReaderRequire(pReader, pNext, nSuffix+FTS3_VARINT_MAX);
1183: if( rc!=SQLITE_OK ) return rc;
1184:
1185: memcpy(&pReader->zTerm[nPrefix], pNext, nSuffix);
1186: pReader->nTerm = nPrefix+nSuffix;
1187: pNext += nSuffix;
1188: pNext += sqlite3Fts3GetVarint32(pNext, &pReader->nDoclist);
1189: pReader->aDoclist = pNext;
1190: pReader->pOffsetList = 0;
1191:
1192: /* Check that the doclist does not appear to extend past the end of the
1193: ** b-tree node. And that the final byte of the doclist is 0x00. If either
1194: ** of these statements is untrue, then the data structure is corrupt.
1195: */
1196: if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode]
1197: || (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1])
1198: ){
1199: return FTS_CORRUPT_VTAB;
1200: }
1201: return SQLITE_OK;
1202: }
1203:
1204: /*
1205: ** Set the SegReader to point to the first docid in the doclist associated
1206: ** with the current term.
1207: */
1208: static int fts3SegReaderFirstDocid(Fts3Table *pTab, Fts3SegReader *pReader){
1209: int rc = SQLITE_OK;
1210: assert( pReader->aDoclist );
1211: assert( !pReader->pOffsetList );
1212: if( pTab->bDescIdx && fts3SegReaderIsPending(pReader) ){
1213: u8 bEof = 0;
1214: pReader->iDocid = 0;
1215: pReader->nOffsetList = 0;
1216: sqlite3Fts3DoclistPrev(0,
1217: pReader->aDoclist, pReader->nDoclist, &pReader->pOffsetList,
1218: &pReader->iDocid, &pReader->nOffsetList, &bEof
1219: );
1220: }else{
1221: rc = fts3SegReaderRequire(pReader, pReader->aDoclist, FTS3_VARINT_MAX);
1222: if( rc==SQLITE_OK ){
1223: int n = sqlite3Fts3GetVarint(pReader->aDoclist, &pReader->iDocid);
1224: pReader->pOffsetList = &pReader->aDoclist[n];
1225: }
1226: }
1227: return rc;
1228: }
1229:
1230: /*
1231: ** Advance the SegReader to point to the next docid in the doclist
1232: ** associated with the current term.
1233: **
1234: ** If arguments ppOffsetList and pnOffsetList are not NULL, then
1235: ** *ppOffsetList is set to point to the first column-offset list
1236: ** in the doclist entry (i.e. immediately past the docid varint).
1237: ** *pnOffsetList is set to the length of the set of column-offset
1238: ** lists, not including the nul-terminator byte. For example:
1239: */
1240: static int fts3SegReaderNextDocid(
1241: Fts3Table *pTab,
1242: Fts3SegReader *pReader, /* Reader to advance to next docid */
1243: char **ppOffsetList, /* OUT: Pointer to current position-list */
1244: int *pnOffsetList /* OUT: Length of *ppOffsetList in bytes */
1245: ){
1246: int rc = SQLITE_OK;
1247: char *p = pReader->pOffsetList;
1248: char c = 0;
1249:
1250: assert( p );
1251:
1252: if( pTab->bDescIdx && fts3SegReaderIsPending(pReader) ){
1253: /* A pending-terms seg-reader for an FTS4 table that uses order=desc.
1254: ** Pending-terms doclists are always built up in ascending order, so
1255: ** we have to iterate through them backwards here. */
1256: u8 bEof = 0;
1257: if( ppOffsetList ){
1258: *ppOffsetList = pReader->pOffsetList;
1259: *pnOffsetList = pReader->nOffsetList - 1;
1260: }
1261: sqlite3Fts3DoclistPrev(0,
1262: pReader->aDoclist, pReader->nDoclist, &p, &pReader->iDocid,
1263: &pReader->nOffsetList, &bEof
1264: );
1265: if( bEof ){
1266: pReader->pOffsetList = 0;
1267: }else{
1268: pReader->pOffsetList = p;
1269: }
1270: }else{
1271: char *pEnd = &pReader->aDoclist[pReader->nDoclist];
1272:
1273: /* Pointer p currently points at the first byte of an offset list. The
1274: ** following block advances it to point one byte past the end of
1275: ** the same offset list. */
1276: while( 1 ){
1277:
1278: /* The following line of code (and the "p++" below the while() loop) is
1279: ** normally all that is required to move pointer p to the desired
1280: ** position. The exception is if this node is being loaded from disk
1281: ** incrementally and pointer "p" now points to the first byte passed
1282: ** the populated part of pReader->aNode[].
1283: */
1284: while( *p | c ) c = *p++ & 0x80;
1285: assert( *p==0 );
1286:
1287: if( pReader->pBlob==0 || p<&pReader->aNode[pReader->nPopulate] ) break;
1288: rc = fts3SegReaderIncrRead(pReader);
1289: if( rc!=SQLITE_OK ) return rc;
1290: }
1291: p++;
1292:
1293: /* If required, populate the output variables with a pointer to and the
1294: ** size of the previous offset-list.
1295: */
1296: if( ppOffsetList ){
1297: *ppOffsetList = pReader->pOffsetList;
1298: *pnOffsetList = (int)(p - pReader->pOffsetList - 1);
1299: }
1300:
1301: while( p<pEnd && *p==0 ) p++;
1302:
1303: /* If there are no more entries in the doclist, set pOffsetList to
1304: ** NULL. Otherwise, set Fts3SegReader.iDocid to the next docid and
1305: ** Fts3SegReader.pOffsetList to point to the next offset list before
1306: ** returning.
1307: */
1308: if( p>=pEnd ){
1309: pReader->pOffsetList = 0;
1310: }else{
1311: rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX);
1312: if( rc==SQLITE_OK ){
1313: sqlite3_int64 iDelta;
1314: pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta);
1315: if( pTab->bDescIdx ){
1316: pReader->iDocid -= iDelta;
1317: }else{
1318: pReader->iDocid += iDelta;
1319: }
1320: }
1321: }
1322: }
1323:
1324: return SQLITE_OK;
1325: }
1326:
1327:
1328: int sqlite3Fts3MsrOvfl(
1329: Fts3Cursor *pCsr,
1330: Fts3MultiSegReader *pMsr,
1331: int *pnOvfl
1332: ){
1333: Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
1334: int nOvfl = 0;
1335: int ii;
1336: int rc = SQLITE_OK;
1337: int pgsz = p->nPgsz;
1338:
1339: assert( p->bHasStat );
1340: assert( pgsz>0 );
1341:
1342: for(ii=0; rc==SQLITE_OK && ii<pMsr->nSegment; ii++){
1343: Fts3SegReader *pReader = pMsr->apSegment[ii];
1344: if( !fts3SegReaderIsPending(pReader)
1345: && !fts3SegReaderIsRootOnly(pReader)
1346: ){
1347: sqlite3_int64 jj;
1348: for(jj=pReader->iStartBlock; jj<=pReader->iLeafEndBlock; jj++){
1349: int nBlob;
1350: rc = sqlite3Fts3ReadBlock(p, jj, 0, &nBlob, 0);
1351: if( rc!=SQLITE_OK ) break;
1352: if( (nBlob+35)>pgsz ){
1353: nOvfl += (nBlob + 34)/pgsz;
1354: }
1355: }
1356: }
1357: }
1358: *pnOvfl = nOvfl;
1359: return rc;
1360: }
1361:
1362: /*
1363: ** Free all allocations associated with the iterator passed as the
1364: ** second argument.
1365: */
1366: void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){
1367: if( pReader && !fts3SegReaderIsPending(pReader) ){
1368: sqlite3_free(pReader->zTerm);
1369: if( !fts3SegReaderIsRootOnly(pReader) ){
1370: sqlite3_free(pReader->aNode);
1371: sqlite3_blob_close(pReader->pBlob);
1372: }
1373: }
1374: sqlite3_free(pReader);
1375: }
1376:
1377: /*
1378: ** Allocate a new SegReader object.
1379: */
1380: int sqlite3Fts3SegReaderNew(
1381: int iAge, /* Segment "age". */
1382: sqlite3_int64 iStartLeaf, /* First leaf to traverse */
1383: sqlite3_int64 iEndLeaf, /* Final leaf to traverse */
1384: sqlite3_int64 iEndBlock, /* Final block of segment */
1385: const char *zRoot, /* Buffer containing root node */
1386: int nRoot, /* Size of buffer containing root node */
1387: Fts3SegReader **ppReader /* OUT: Allocated Fts3SegReader */
1388: ){
1389: Fts3SegReader *pReader; /* Newly allocated SegReader object */
1390: int nExtra = 0; /* Bytes to allocate segment root node */
1391:
1392: assert( iStartLeaf<=iEndLeaf );
1393: if( iStartLeaf==0 ){
1394: nExtra = nRoot + FTS3_NODE_PADDING;
1395: }
1396:
1397: pReader = (Fts3SegReader *)sqlite3_malloc(sizeof(Fts3SegReader) + nExtra);
1398: if( !pReader ){
1399: return SQLITE_NOMEM;
1400: }
1401: memset(pReader, 0, sizeof(Fts3SegReader));
1402: pReader->iIdx = iAge;
1403: pReader->iStartBlock = iStartLeaf;
1404: pReader->iLeafEndBlock = iEndLeaf;
1405: pReader->iEndBlock = iEndBlock;
1406:
1407: if( nExtra ){
1408: /* The entire segment is stored in the root node. */
1409: pReader->aNode = (char *)&pReader[1];
1410: pReader->nNode = nRoot;
1411: memcpy(pReader->aNode, zRoot, nRoot);
1412: memset(&pReader->aNode[nRoot], 0, FTS3_NODE_PADDING);
1413: }else{
1414: pReader->iCurrentBlock = iStartLeaf-1;
1415: }
1416: *ppReader = pReader;
1417: return SQLITE_OK;
1418: }
1419:
1420: /*
1421: ** This is a comparison function used as a qsort() callback when sorting
1422: ** an array of pending terms by term. This occurs as part of flushing
1423: ** the contents of the pending-terms hash table to the database.
1424: */
1425: static int fts3CompareElemByTerm(const void *lhs, const void *rhs){
1426: char *z1 = fts3HashKey(*(Fts3HashElem **)lhs);
1427: char *z2 = fts3HashKey(*(Fts3HashElem **)rhs);
1428: int n1 = fts3HashKeysize(*(Fts3HashElem **)lhs);
1429: int n2 = fts3HashKeysize(*(Fts3HashElem **)rhs);
1430:
1431: int n = (n1<n2 ? n1 : n2);
1432: int c = memcmp(z1, z2, n);
1433: if( c==0 ){
1434: c = n1 - n2;
1435: }
1436: return c;
1437: }
1438:
1439: /*
1440: ** This function is used to allocate an Fts3SegReader that iterates through
1441: ** a subset of the terms stored in the Fts3Table.pendingTerms array.
1442: **
1443: ** If the isPrefixIter parameter is zero, then the returned SegReader iterates
1444: ** through each term in the pending-terms table. Or, if isPrefixIter is
1445: ** non-zero, it iterates through each term and its prefixes. For example, if
1446: ** the pending terms hash table contains the terms "sqlite", "mysql" and
1447: ** "firebird", then the iterator visits the following 'terms' (in the order
1448: ** shown):
1449: **
1450: ** f fi fir fire fireb firebi firebir firebird
1451: ** m my mys mysq mysql
1452: ** s sq sql sqli sqlit sqlite
1453: **
1454: ** Whereas if isPrefixIter is zero, the terms visited are:
1455: **
1456: ** firebird mysql sqlite
1457: */
1458: int sqlite3Fts3SegReaderPending(
1459: Fts3Table *p, /* Virtual table handle */
1460: int iIndex, /* Index for p->aIndex */
1461: const char *zTerm, /* Term to search for */
1462: int nTerm, /* Size of buffer zTerm */
1463: int bPrefix, /* True for a prefix iterator */
1464: Fts3SegReader **ppReader /* OUT: SegReader for pending-terms */
1465: ){
1466: Fts3SegReader *pReader = 0; /* Fts3SegReader object to return */
1467: Fts3HashElem *pE; /* Iterator variable */
1468: Fts3HashElem **aElem = 0; /* Array of term hash entries to scan */
1469: int nElem = 0; /* Size of array at aElem */
1470: int rc = SQLITE_OK; /* Return Code */
1471: Fts3Hash *pHash;
1472:
1473: pHash = &p->aIndex[iIndex].hPending;
1474: if( bPrefix ){
1475: int nAlloc = 0; /* Size of allocated array at aElem */
1476:
1477: for(pE=fts3HashFirst(pHash); pE; pE=fts3HashNext(pE)){
1478: char *zKey = (char *)fts3HashKey(pE);
1479: int nKey = fts3HashKeysize(pE);
1480: if( nTerm==0 || (nKey>=nTerm && 0==memcmp(zKey, zTerm, nTerm)) ){
1481: if( nElem==nAlloc ){
1482: Fts3HashElem **aElem2;
1483: nAlloc += 16;
1484: aElem2 = (Fts3HashElem **)sqlite3_realloc(
1485: aElem, nAlloc*sizeof(Fts3HashElem *)
1486: );
1487: if( !aElem2 ){
1488: rc = SQLITE_NOMEM;
1489: nElem = 0;
1490: break;
1491: }
1492: aElem = aElem2;
1493: }
1494:
1495: aElem[nElem++] = pE;
1496: }
1497: }
1498:
1499: /* If more than one term matches the prefix, sort the Fts3HashElem
1500: ** objects in term order using qsort(). This uses the same comparison
1501: ** callback as is used when flushing terms to disk.
1502: */
1503: if( nElem>1 ){
1504: qsort(aElem, nElem, sizeof(Fts3HashElem *), fts3CompareElemByTerm);
1505: }
1506:
1507: }else{
1508: /* The query is a simple term lookup that matches at most one term in
1509: ** the index. All that is required is a straight hash-lookup.
1510: **
1511: ** Because the stack address of pE may be accessed via the aElem pointer
1512: ** below, the "Fts3HashElem *pE" must be declared so that it is valid
1513: ** within this entire function, not just this "else{...}" block.
1514: */
1515: pE = fts3HashFindElem(pHash, zTerm, nTerm);
1516: if( pE ){
1517: aElem = &pE;
1518: nElem = 1;
1519: }
1520: }
1521:
1522: if( nElem>0 ){
1523: int nByte = sizeof(Fts3SegReader) + (nElem+1)*sizeof(Fts3HashElem *);
1524: pReader = (Fts3SegReader *)sqlite3_malloc(nByte);
1525: if( !pReader ){
1526: rc = SQLITE_NOMEM;
1527: }else{
1528: memset(pReader, 0, nByte);
1529: pReader->iIdx = 0x7FFFFFFF;
1530: pReader->ppNextElem = (Fts3HashElem **)&pReader[1];
1531: memcpy(pReader->ppNextElem, aElem, nElem*sizeof(Fts3HashElem *));
1532: }
1533: }
1534:
1535: if( bPrefix ){
1536: sqlite3_free(aElem);
1537: }
1538: *ppReader = pReader;
1539: return rc;
1540: }
1541:
1542: /*
1543: ** Compare the entries pointed to by two Fts3SegReader structures.
1544: ** Comparison is as follows:
1545: **
1546: ** 1) EOF is greater than not EOF.
1547: **
1548: ** 2) The current terms (if any) are compared using memcmp(). If one
1549: ** term is a prefix of another, the longer term is considered the
1550: ** larger.
1551: **
1552: ** 3) By segment age. An older segment is considered larger.
1553: */
1554: static int fts3SegReaderCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
1555: int rc;
1556: if( pLhs->aNode && pRhs->aNode ){
1557: int rc2 = pLhs->nTerm - pRhs->nTerm;
1558: if( rc2<0 ){
1559: rc = memcmp(pLhs->zTerm, pRhs->zTerm, pLhs->nTerm);
1560: }else{
1561: rc = memcmp(pLhs->zTerm, pRhs->zTerm, pRhs->nTerm);
1562: }
1563: if( rc==0 ){
1564: rc = rc2;
1565: }
1566: }else{
1567: rc = (pLhs->aNode==0) - (pRhs->aNode==0);
1568: }
1569: if( rc==0 ){
1570: rc = pRhs->iIdx - pLhs->iIdx;
1571: }
1572: assert( rc!=0 );
1573: return rc;
1574: }
1575:
1576: /*
1577: ** A different comparison function for SegReader structures. In this
1578: ** version, it is assumed that each SegReader points to an entry in
1579: ** a doclist for identical terms. Comparison is made as follows:
1580: **
1581: ** 1) EOF (end of doclist in this case) is greater than not EOF.
1582: **
1583: ** 2) By current docid.
1584: **
1585: ** 3) By segment age. An older segment is considered larger.
1586: */
1587: static int fts3SegReaderDoclistCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
1588: int rc = (pLhs->pOffsetList==0)-(pRhs->pOffsetList==0);
1589: if( rc==0 ){
1590: if( pLhs->iDocid==pRhs->iDocid ){
1591: rc = pRhs->iIdx - pLhs->iIdx;
1592: }else{
1593: rc = (pLhs->iDocid > pRhs->iDocid) ? 1 : -1;
1594: }
1595: }
1596: assert( pLhs->aNode && pRhs->aNode );
1597: return rc;
1598: }
1599: static int fts3SegReaderDoclistCmpRev(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
1600: int rc = (pLhs->pOffsetList==0)-(pRhs->pOffsetList==0);
1601: if( rc==0 ){
1602: if( pLhs->iDocid==pRhs->iDocid ){
1603: rc = pRhs->iIdx - pLhs->iIdx;
1604: }else{
1605: rc = (pLhs->iDocid < pRhs->iDocid) ? 1 : -1;
1606: }
1607: }
1608: assert( pLhs->aNode && pRhs->aNode );
1609: return rc;
1610: }
1611:
1612: /*
1613: ** Compare the term that the Fts3SegReader object passed as the first argument
1614: ** points to with the term specified by arguments zTerm and nTerm.
1615: **
1616: ** If the pSeg iterator is already at EOF, return 0. Otherwise, return
1617: ** -ve if the pSeg term is less than zTerm/nTerm, 0 if the two terms are
1618: ** equal, or +ve if the pSeg term is greater than zTerm/nTerm.
1619: */
1620: static int fts3SegReaderTermCmp(
1621: Fts3SegReader *pSeg, /* Segment reader object */
1622: const char *zTerm, /* Term to compare to */
1623: int nTerm /* Size of term zTerm in bytes */
1624: ){
1625: int res = 0;
1626: if( pSeg->aNode ){
1627: if( pSeg->nTerm>nTerm ){
1628: res = memcmp(pSeg->zTerm, zTerm, nTerm);
1629: }else{
1630: res = memcmp(pSeg->zTerm, zTerm, pSeg->nTerm);
1631: }
1632: if( res==0 ){
1633: res = pSeg->nTerm-nTerm;
1634: }
1635: }
1636: return res;
1637: }
1638:
1639: /*
1640: ** Argument apSegment is an array of nSegment elements. It is known that
1641: ** the final (nSegment-nSuspect) members are already in sorted order
1642: ** (according to the comparison function provided). This function shuffles
1643: ** the array around until all entries are in sorted order.
1644: */
1645: static void fts3SegReaderSort(
1646: Fts3SegReader **apSegment, /* Array to sort entries of */
1647: int nSegment, /* Size of apSegment array */
1648: int nSuspect, /* Unsorted entry count */
1649: int (*xCmp)(Fts3SegReader *, Fts3SegReader *) /* Comparison function */
1650: ){
1651: int i; /* Iterator variable */
1652:
1653: assert( nSuspect<=nSegment );
1654:
1655: if( nSuspect==nSegment ) nSuspect--;
1656: for(i=nSuspect-1; i>=0; i--){
1657: int j;
1658: for(j=i; j<(nSegment-1); j++){
1659: Fts3SegReader *pTmp;
1660: if( xCmp(apSegment[j], apSegment[j+1])<0 ) break;
1661: pTmp = apSegment[j+1];
1662: apSegment[j+1] = apSegment[j];
1663: apSegment[j] = pTmp;
1664: }
1665: }
1666:
1667: #ifndef NDEBUG
1668: /* Check that the list really is sorted now. */
1669: for(i=0; i<(nSuspect-1); i++){
1670: assert( xCmp(apSegment[i], apSegment[i+1])<0 );
1671: }
1672: #endif
1673: }
1674:
1675: /*
1676: ** Insert a record into the %_segments table.
1677: */
1678: static int fts3WriteSegment(
1679: Fts3Table *p, /* Virtual table handle */
1680: sqlite3_int64 iBlock, /* Block id for new block */
1681: char *z, /* Pointer to buffer containing block data */
1682: int n /* Size of buffer z in bytes */
1683: ){
1684: sqlite3_stmt *pStmt;
1685: int rc = fts3SqlStmt(p, SQL_INSERT_SEGMENTS, &pStmt, 0);
1686: if( rc==SQLITE_OK ){
1687: sqlite3_bind_int64(pStmt, 1, iBlock);
1688: sqlite3_bind_blob(pStmt, 2, z, n, SQLITE_STATIC);
1689: sqlite3_step(pStmt);
1690: rc = sqlite3_reset(pStmt);
1691: }
1692: return rc;
1693: }
1694:
1695: /*
1696: ** Insert a record into the %_segdir table.
1697: */
1698: static int fts3WriteSegdir(
1699: Fts3Table *p, /* Virtual table handle */
1700: int iLevel, /* Value for "level" field */
1701: int iIdx, /* Value for "idx" field */
1702: sqlite3_int64 iStartBlock, /* Value for "start_block" field */
1703: sqlite3_int64 iLeafEndBlock, /* Value for "leaves_end_block" field */
1704: sqlite3_int64 iEndBlock, /* Value for "end_block" field */
1705: char *zRoot, /* Blob value for "root" field */
1706: int nRoot /* Number of bytes in buffer zRoot */
1707: ){
1708: sqlite3_stmt *pStmt;
1709: int rc = fts3SqlStmt(p, SQL_INSERT_SEGDIR, &pStmt, 0);
1710: if( rc==SQLITE_OK ){
1711: sqlite3_bind_int(pStmt, 1, iLevel);
1712: sqlite3_bind_int(pStmt, 2, iIdx);
1713: sqlite3_bind_int64(pStmt, 3, iStartBlock);
1714: sqlite3_bind_int64(pStmt, 4, iLeafEndBlock);
1715: sqlite3_bind_int64(pStmt, 5, iEndBlock);
1716: sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC);
1717: sqlite3_step(pStmt);
1718: rc = sqlite3_reset(pStmt);
1719: }
1720: return rc;
1721: }
1722:
1723: /*
1724: ** Return the size of the common prefix (if any) shared by zPrev and
1725: ** zNext, in bytes. For example,
1726: **
1727: ** fts3PrefixCompress("abc", 3, "abcdef", 6) // returns 3
1728: ** fts3PrefixCompress("abX", 3, "abcdef", 6) // returns 2
1729: ** fts3PrefixCompress("abX", 3, "Xbcdef", 6) // returns 0
1730: */
1731: static int fts3PrefixCompress(
1732: const char *zPrev, /* Buffer containing previous term */
1733: int nPrev, /* Size of buffer zPrev in bytes */
1734: const char *zNext, /* Buffer containing next term */
1735: int nNext /* Size of buffer zNext in bytes */
1736: ){
1737: int n;
1738: UNUSED_PARAMETER(nNext);
1739: for(n=0; n<nPrev && zPrev[n]==zNext[n]; n++);
1740: return n;
1741: }
1742:
1743: /*
1744: ** Add term zTerm to the SegmentNode. It is guaranteed that zTerm is larger
1745: ** (according to memcmp) than the previous term.
1746: */
1747: static int fts3NodeAddTerm(
1748: Fts3Table *p, /* Virtual table handle */
1749: SegmentNode **ppTree, /* IN/OUT: SegmentNode handle */
1750: int isCopyTerm, /* True if zTerm/nTerm is transient */
1751: const char *zTerm, /* Pointer to buffer containing term */
1752: int nTerm /* Size of term in bytes */
1753: ){
1754: SegmentNode *pTree = *ppTree;
1755: int rc;
1756: SegmentNode *pNew;
1757:
1758: /* First try to append the term to the current node. Return early if
1759: ** this is possible.
1760: */
1761: if( pTree ){
1762: int nData = pTree->nData; /* Current size of node in bytes */
1763: int nReq = nData; /* Required space after adding zTerm */
1764: int nPrefix; /* Number of bytes of prefix compression */
1765: int nSuffix; /* Suffix length */
1766:
1767: nPrefix = fts3PrefixCompress(pTree->zTerm, pTree->nTerm, zTerm, nTerm);
1768: nSuffix = nTerm-nPrefix;
1769:
1770: nReq += sqlite3Fts3VarintLen(nPrefix)+sqlite3Fts3VarintLen(nSuffix)+nSuffix;
1771: if( nReq<=p->nNodeSize || !pTree->zTerm ){
1772:
1773: if( nReq>p->nNodeSize ){
1774: /* An unusual case: this is the first term to be added to the node
1775: ** and the static node buffer (p->nNodeSize bytes) is not large
1776: ** enough. Use a separately malloced buffer instead This wastes
1777: ** p->nNodeSize bytes, but since this scenario only comes about when
1778: ** the database contain two terms that share a prefix of almost 2KB,
1779: ** this is not expected to be a serious problem.
1780: */
1781: assert( pTree->aData==(char *)&pTree[1] );
1782: pTree->aData = (char *)sqlite3_malloc(nReq);
1783: if( !pTree->aData ){
1784: return SQLITE_NOMEM;
1785: }
1786: }
1787:
1788: if( pTree->zTerm ){
1789: /* There is no prefix-length field for first term in a node */
1790: nData += sqlite3Fts3PutVarint(&pTree->aData[nData], nPrefix);
1791: }
1792:
1793: nData += sqlite3Fts3PutVarint(&pTree->aData[nData], nSuffix);
1794: memcpy(&pTree->aData[nData], &zTerm[nPrefix], nSuffix);
1795: pTree->nData = nData + nSuffix;
1796: pTree->nEntry++;
1797:
1798: if( isCopyTerm ){
1799: if( pTree->nMalloc<nTerm ){
1800: char *zNew = sqlite3_realloc(pTree->zMalloc, nTerm*2);
1801: if( !zNew ){
1802: return SQLITE_NOMEM;
1803: }
1804: pTree->nMalloc = nTerm*2;
1805: pTree->zMalloc = zNew;
1806: }
1807: pTree->zTerm = pTree->zMalloc;
1808: memcpy(pTree->zTerm, zTerm, nTerm);
1809: pTree->nTerm = nTerm;
1810: }else{
1811: pTree->zTerm = (char *)zTerm;
1812: pTree->nTerm = nTerm;
1813: }
1814: return SQLITE_OK;
1815: }
1816: }
1817:
1818: /* If control flows to here, it was not possible to append zTerm to the
1819: ** current node. Create a new node (a right-sibling of the current node).
1820: ** If this is the first node in the tree, the term is added to it.
1821: **
1822: ** Otherwise, the term is not added to the new node, it is left empty for
1823: ** now. Instead, the term is inserted into the parent of pTree. If pTree
1824: ** has no parent, one is created here.
1825: */
1826: pNew = (SegmentNode *)sqlite3_malloc(sizeof(SegmentNode) + p->nNodeSize);
1827: if( !pNew ){
1828: return SQLITE_NOMEM;
1829: }
1830: memset(pNew, 0, sizeof(SegmentNode));
1831: pNew->nData = 1 + FTS3_VARINT_MAX;
1832: pNew->aData = (char *)&pNew[1];
1833:
1834: if( pTree ){
1835: SegmentNode *pParent = pTree->pParent;
1836: rc = fts3NodeAddTerm(p, &pParent, isCopyTerm, zTerm, nTerm);
1837: if( pTree->pParent==0 ){
1838: pTree->pParent = pParent;
1839: }
1840: pTree->pRight = pNew;
1841: pNew->pLeftmost = pTree->pLeftmost;
1842: pNew->pParent = pParent;
1843: pNew->zMalloc = pTree->zMalloc;
1844: pNew->nMalloc = pTree->nMalloc;
1845: pTree->zMalloc = 0;
1846: }else{
1847: pNew->pLeftmost = pNew;
1848: rc = fts3NodeAddTerm(p, &pNew, isCopyTerm, zTerm, nTerm);
1849: }
1850:
1851: *ppTree = pNew;
1852: return rc;
1853: }
1854:
1855: /*
1856: ** Helper function for fts3NodeWrite().
1857: */
1858: static int fts3TreeFinishNode(
1859: SegmentNode *pTree,
1860: int iHeight,
1861: sqlite3_int64 iLeftChild
1862: ){
1863: int nStart;
1864: assert( iHeight>=1 && iHeight<128 );
1865: nStart = FTS3_VARINT_MAX - sqlite3Fts3VarintLen(iLeftChild);
1866: pTree->aData[nStart] = (char)iHeight;
1867: sqlite3Fts3PutVarint(&pTree->aData[nStart+1], iLeftChild);
1868: return nStart;
1869: }
1870:
1871: /*
1872: ** Write the buffer for the segment node pTree and all of its peers to the
1873: ** database. Then call this function recursively to write the parent of
1874: ** pTree and its peers to the database.
1875: **
1876: ** Except, if pTree is a root node, do not write it to the database. Instead,
1877: ** set output variables *paRoot and *pnRoot to contain the root node.
1878: **
1879: ** If successful, SQLITE_OK is returned and output variable *piLast is
1880: ** set to the largest blockid written to the database (or zero if no
1881: ** blocks were written to the db). Otherwise, an SQLite error code is
1882: ** returned.
1883: */
1884: static int fts3NodeWrite(
1885: Fts3Table *p, /* Virtual table handle */
1886: SegmentNode *pTree, /* SegmentNode handle */
1887: int iHeight, /* Height of this node in tree */
1888: sqlite3_int64 iLeaf, /* Block id of first leaf node */
1889: sqlite3_int64 iFree, /* Block id of next free slot in %_segments */
1890: sqlite3_int64 *piLast, /* OUT: Block id of last entry written */
1891: char **paRoot, /* OUT: Data for root node */
1892: int *pnRoot /* OUT: Size of root node in bytes */
1893: ){
1894: int rc = SQLITE_OK;
1895:
1896: if( !pTree->pParent ){
1897: /* Root node of the tree. */
1898: int nStart = fts3TreeFinishNode(pTree, iHeight, iLeaf);
1899: *piLast = iFree-1;
1900: *pnRoot = pTree->nData - nStart;
1901: *paRoot = &pTree->aData[nStart];
1902: }else{
1903: SegmentNode *pIter;
1904: sqlite3_int64 iNextFree = iFree;
1905: sqlite3_int64 iNextLeaf = iLeaf;
1906: for(pIter=pTree->pLeftmost; pIter && rc==SQLITE_OK; pIter=pIter->pRight){
1907: int nStart = fts3TreeFinishNode(pIter, iHeight, iNextLeaf);
1908: int nWrite = pIter->nData - nStart;
1909:
1910: rc = fts3WriteSegment(p, iNextFree, &pIter->aData[nStart], nWrite);
1911: iNextFree++;
1912: iNextLeaf += (pIter->nEntry+1);
1913: }
1914: if( rc==SQLITE_OK ){
1915: assert( iNextLeaf==iFree );
1916: rc = fts3NodeWrite(
1917: p, pTree->pParent, iHeight+1, iFree, iNextFree, piLast, paRoot, pnRoot
1918: );
1919: }
1920: }
1921:
1922: return rc;
1923: }
1924:
1925: /*
1926: ** Free all memory allocations associated with the tree pTree.
1927: */
1928: static void fts3NodeFree(SegmentNode *pTree){
1929: if( pTree ){
1930: SegmentNode *p = pTree->pLeftmost;
1931: fts3NodeFree(p->pParent);
1932: while( p ){
1933: SegmentNode *pRight = p->pRight;
1934: if( p->aData!=(char *)&p[1] ){
1935: sqlite3_free(p->aData);
1936: }
1937: assert( pRight==0 || p->zMalloc==0 );
1938: sqlite3_free(p->zMalloc);
1939: sqlite3_free(p);
1940: p = pRight;
1941: }
1942: }
1943: }
1944:
1945: /*
1946: ** Add a term to the segment being constructed by the SegmentWriter object
1947: ** *ppWriter. When adding the first term to a segment, *ppWriter should
1948: ** be passed NULL. This function will allocate a new SegmentWriter object
1949: ** and return it via the input/output variable *ppWriter in this case.
1950: **
1951: ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code.
1952: */
1953: static int fts3SegWriterAdd(
1954: Fts3Table *p, /* Virtual table handle */
1955: SegmentWriter **ppWriter, /* IN/OUT: SegmentWriter handle */
1956: int isCopyTerm, /* True if buffer zTerm must be copied */
1957: const char *zTerm, /* Pointer to buffer containing term */
1958: int nTerm, /* Size of term in bytes */
1959: const char *aDoclist, /* Pointer to buffer containing doclist */
1960: int nDoclist /* Size of doclist in bytes */
1961: ){
1962: int nPrefix; /* Size of term prefix in bytes */
1963: int nSuffix; /* Size of term suffix in bytes */
1964: int nReq; /* Number of bytes required on leaf page */
1965: int nData;
1966: SegmentWriter *pWriter = *ppWriter;
1967:
1968: if( !pWriter ){
1969: int rc;
1970: sqlite3_stmt *pStmt;
1971:
1972: /* Allocate the SegmentWriter structure */
1973: pWriter = (SegmentWriter *)sqlite3_malloc(sizeof(SegmentWriter));
1974: if( !pWriter ) return SQLITE_NOMEM;
1975: memset(pWriter, 0, sizeof(SegmentWriter));
1976: *ppWriter = pWriter;
1977:
1978: /* Allocate a buffer in which to accumulate data */
1979: pWriter->aData = (char *)sqlite3_malloc(p->nNodeSize);
1980: if( !pWriter->aData ) return SQLITE_NOMEM;
1981: pWriter->nSize = p->nNodeSize;
1982:
1983: /* Find the next free blockid in the %_segments table */
1984: rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pStmt, 0);
1985: if( rc!=SQLITE_OK ) return rc;
1986: if( SQLITE_ROW==sqlite3_step(pStmt) ){
1987: pWriter->iFree = sqlite3_column_int64(pStmt, 0);
1988: pWriter->iFirst = pWriter->iFree;
1989: }
1990: rc = sqlite3_reset(pStmt);
1991: if( rc!=SQLITE_OK ) return rc;
1992: }
1993: nData = pWriter->nData;
1994:
1995: nPrefix = fts3PrefixCompress(pWriter->zTerm, pWriter->nTerm, zTerm, nTerm);
1996: nSuffix = nTerm-nPrefix;
1997:
1998: /* Figure out how many bytes are required by this new entry */
1999: nReq = sqlite3Fts3VarintLen(nPrefix) + /* varint containing prefix size */
2000: sqlite3Fts3VarintLen(nSuffix) + /* varint containing suffix size */
2001: nSuffix + /* Term suffix */
2002: sqlite3Fts3VarintLen(nDoclist) + /* Size of doclist */
2003: nDoclist; /* Doclist data */
2004:
2005: if( nData>0 && nData+nReq>p->nNodeSize ){
2006: int rc;
2007:
2008: /* The current leaf node is full. Write it out to the database. */
2009: rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData);
2010: if( rc!=SQLITE_OK ) return rc;
2011:
2012: /* Add the current term to the interior node tree. The term added to
2013: ** the interior tree must:
2014: **
2015: ** a) be greater than the largest term on the leaf node just written
2016: ** to the database (still available in pWriter->zTerm), and
2017: **
2018: ** b) be less than or equal to the term about to be added to the new
2019: ** leaf node (zTerm/nTerm).
2020: **
2021: ** In other words, it must be the prefix of zTerm 1 byte longer than
2022: ** the common prefix (if any) of zTerm and pWriter->zTerm.
2023: */
2024: assert( nPrefix<nTerm );
2025: rc = fts3NodeAddTerm(p, &pWriter->pTree, isCopyTerm, zTerm, nPrefix+1);
2026: if( rc!=SQLITE_OK ) return rc;
2027:
2028: nData = 0;
2029: pWriter->nTerm = 0;
2030:
2031: nPrefix = 0;
2032: nSuffix = nTerm;
2033: nReq = 1 + /* varint containing prefix size */
2034: sqlite3Fts3VarintLen(nTerm) + /* varint containing suffix size */
2035: nTerm + /* Term suffix */
2036: sqlite3Fts3VarintLen(nDoclist) + /* Size of doclist */
2037: nDoclist; /* Doclist data */
2038: }
2039:
2040: /* If the buffer currently allocated is too small for this entry, realloc
2041: ** the buffer to make it large enough.
2042: */
2043: if( nReq>pWriter->nSize ){
2044: char *aNew = sqlite3_realloc(pWriter->aData, nReq);
2045: if( !aNew ) return SQLITE_NOMEM;
2046: pWriter->aData = aNew;
2047: pWriter->nSize = nReq;
2048: }
2049: assert( nData+nReq<=pWriter->nSize );
2050:
2051: /* Append the prefix-compressed term and doclist to the buffer. */
2052: nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nPrefix);
2053: nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nSuffix);
2054: memcpy(&pWriter->aData[nData], &zTerm[nPrefix], nSuffix);
2055: nData += nSuffix;
2056: nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nDoclist);
2057: memcpy(&pWriter->aData[nData], aDoclist, nDoclist);
2058: pWriter->nData = nData + nDoclist;
2059:
2060: /* Save the current term so that it can be used to prefix-compress the next.
2061: ** If the isCopyTerm parameter is true, then the buffer pointed to by
2062: ** zTerm is transient, so take a copy of the term data. Otherwise, just
2063: ** store a copy of the pointer.
2064: */
2065: if( isCopyTerm ){
2066: if( nTerm>pWriter->nMalloc ){
2067: char *zNew = sqlite3_realloc(pWriter->zMalloc, nTerm*2);
2068: if( !zNew ){
2069: return SQLITE_NOMEM;
2070: }
2071: pWriter->nMalloc = nTerm*2;
2072: pWriter->zMalloc = zNew;
2073: pWriter->zTerm = zNew;
2074: }
2075: assert( pWriter->zTerm==pWriter->zMalloc );
2076: memcpy(pWriter->zTerm, zTerm, nTerm);
2077: }else{
2078: pWriter->zTerm = (char *)zTerm;
2079: }
2080: pWriter->nTerm = nTerm;
2081:
2082: return SQLITE_OK;
2083: }
2084:
2085: /*
2086: ** Flush all data associated with the SegmentWriter object pWriter to the
2087: ** database. This function must be called after all terms have been added
2088: ** to the segment using fts3SegWriterAdd(). If successful, SQLITE_OK is
2089: ** returned. Otherwise, an SQLite error code.
2090: */
2091: static int fts3SegWriterFlush(
2092: Fts3Table *p, /* Virtual table handle */
2093: SegmentWriter *pWriter, /* SegmentWriter to flush to the db */
2094: int iLevel, /* Value for 'level' column of %_segdir */
2095: int iIdx /* Value for 'idx' column of %_segdir */
2096: ){
2097: int rc; /* Return code */
2098: if( pWriter->pTree ){
2099: sqlite3_int64 iLast = 0; /* Largest block id written to database */
2100: sqlite3_int64 iLastLeaf; /* Largest leaf block id written to db */
2101: char *zRoot = NULL; /* Pointer to buffer containing root node */
2102: int nRoot = 0; /* Size of buffer zRoot */
2103:
2104: iLastLeaf = pWriter->iFree;
2105: rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, pWriter->nData);
2106: if( rc==SQLITE_OK ){
2107: rc = fts3NodeWrite(p, pWriter->pTree, 1,
2108: pWriter->iFirst, pWriter->iFree, &iLast, &zRoot, &nRoot);
2109: }
2110: if( rc==SQLITE_OK ){
2111: rc = fts3WriteSegdir(
2112: p, iLevel, iIdx, pWriter->iFirst, iLastLeaf, iLast, zRoot, nRoot);
2113: }
2114: }else{
2115: /* The entire tree fits on the root node. Write it to the segdir table. */
2116: rc = fts3WriteSegdir(
2117: p, iLevel, iIdx, 0, 0, 0, pWriter->aData, pWriter->nData);
2118: }
2119: return rc;
2120: }
2121:
2122: /*
2123: ** Release all memory held by the SegmentWriter object passed as the
2124: ** first argument.
2125: */
2126: static void fts3SegWriterFree(SegmentWriter *pWriter){
2127: if( pWriter ){
2128: sqlite3_free(pWriter->aData);
2129: sqlite3_free(pWriter->zMalloc);
2130: fts3NodeFree(pWriter->pTree);
2131: sqlite3_free(pWriter);
2132: }
2133: }
2134:
2135: /*
2136: ** The first value in the apVal[] array is assumed to contain an integer.
2137: ** This function tests if there exist any documents with docid values that
2138: ** are different from that integer. i.e. if deleting the document with docid
2139: ** pRowid would mean the FTS3 table were empty.
2140: **
2141: ** If successful, *pisEmpty is set to true if the table is empty except for
2142: ** document pRowid, or false otherwise, and SQLITE_OK is returned. If an
2143: ** error occurs, an SQLite error code is returned.
2144: */
2145: static int fts3IsEmpty(Fts3Table *p, sqlite3_value *pRowid, int *pisEmpty){
2146: sqlite3_stmt *pStmt;
2147: int rc;
2148: if( p->zContentTbl ){
2149: /* If using the content=xxx option, assume the table is never empty */
2150: *pisEmpty = 0;
2151: rc = SQLITE_OK;
2152: }else{
2153: rc = fts3SqlStmt(p, SQL_IS_EMPTY, &pStmt, &pRowid);
2154: if( rc==SQLITE_OK ){
2155: if( SQLITE_ROW==sqlite3_step(pStmt) ){
2156: *pisEmpty = sqlite3_column_int(pStmt, 0);
2157: }
2158: rc = sqlite3_reset(pStmt);
2159: }
2160: }
2161: return rc;
2162: }
2163:
2164: /*
2165: ** Set *pnMax to the largest segment level in the database for the index
2166: ** iIndex.
2167: **
2168: ** Segment levels are stored in the 'level' column of the %_segdir table.
2169: **
2170: ** Return SQLITE_OK if successful, or an SQLite error code if not.
2171: */
2172: static int fts3SegmentMaxLevel(Fts3Table *p, int iIndex, int *pnMax){
2173: sqlite3_stmt *pStmt;
2174: int rc;
2175: assert( iIndex>=0 && iIndex<p->nIndex );
2176:
2177: /* Set pStmt to the compiled version of:
2178: **
2179: ** SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?
2180: **
2181: ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR).
2182: */
2183: rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0);
2184: if( rc!=SQLITE_OK ) return rc;
2185: sqlite3_bind_int(pStmt, 1, iIndex*FTS3_SEGDIR_MAXLEVEL);
2186: sqlite3_bind_int(pStmt, 2, (iIndex+1)*FTS3_SEGDIR_MAXLEVEL - 1);
2187: if( SQLITE_ROW==sqlite3_step(pStmt) ){
2188: *pnMax = sqlite3_column_int(pStmt, 0);
2189: }
2190: return sqlite3_reset(pStmt);
2191: }
2192:
2193: /*
2194: ** This function is used after merging multiple segments into a single large
2195: ** segment to delete the old, now redundant, segment b-trees. Specifically,
2196: ** it:
2197: **
2198: ** 1) Deletes all %_segments entries for the segments associated with
2199: ** each of the SegReader objects in the array passed as the third
2200: ** argument, and
2201: **
2202: ** 2) deletes all %_segdir entries with level iLevel, or all %_segdir
2203: ** entries regardless of level if (iLevel<0).
2204: **
2205: ** SQLITE_OK is returned if successful, otherwise an SQLite error code.
2206: */
2207: static int fts3DeleteSegdir(
2208: Fts3Table *p, /* Virtual table handle */
2209: int iIndex, /* Index for p->aIndex */
2210: int iLevel, /* Level of %_segdir entries to delete */
2211: Fts3SegReader **apSegment, /* Array of SegReader objects */
2212: int nReader /* Size of array apSegment */
2213: ){
2214: int rc; /* Return Code */
2215: int i; /* Iterator variable */
2216: sqlite3_stmt *pDelete; /* SQL statement to delete rows */
2217:
2218: rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDelete, 0);
2219: for(i=0; rc==SQLITE_OK && i<nReader; i++){
2220: Fts3SegReader *pSegment = apSegment[i];
2221: if( pSegment->iStartBlock ){
2222: sqlite3_bind_int64(pDelete, 1, pSegment->iStartBlock);
2223: sqlite3_bind_int64(pDelete, 2, pSegment->iEndBlock);
2224: sqlite3_step(pDelete);
2225: rc = sqlite3_reset(pDelete);
2226: }
2227: }
2228: if( rc!=SQLITE_OK ){
2229: return rc;
2230: }
2231:
2232: assert( iLevel>=0 || iLevel==FTS3_SEGCURSOR_ALL );
2233: if( iLevel==FTS3_SEGCURSOR_ALL ){
2234: rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_RANGE, &pDelete, 0);
2235: if( rc==SQLITE_OK ){
2236: sqlite3_bind_int(pDelete, 1, iIndex*FTS3_SEGDIR_MAXLEVEL);
2237: sqlite3_bind_int(pDelete, 2, (iIndex+1) * FTS3_SEGDIR_MAXLEVEL - 1);
2238: }
2239: }else{
2240: rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pDelete, 0);
2241: if( rc==SQLITE_OK ){
2242: sqlite3_bind_int(pDelete, 1, iIndex*FTS3_SEGDIR_MAXLEVEL + iLevel);
2243: }
2244: }
2245:
2246: if( rc==SQLITE_OK ){
2247: sqlite3_step(pDelete);
2248: rc = sqlite3_reset(pDelete);
2249: }
2250:
2251: return rc;
2252: }
2253:
2254: /*
2255: ** When this function is called, buffer *ppList (size *pnList bytes) contains
2256: ** a position list that may (or may not) feature multiple columns. This
2257: ** function adjusts the pointer *ppList and the length *pnList so that they
2258: ** identify the subset of the position list that corresponds to column iCol.
2259: **
2260: ** If there are no entries in the input position list for column iCol, then
2261: ** *pnList is set to zero before returning.
2262: */
2263: static void fts3ColumnFilter(
2264: int iCol, /* Column to filter on */
2265: char **ppList, /* IN/OUT: Pointer to position list */
2266: int *pnList /* IN/OUT: Size of buffer *ppList in bytes */
2267: ){
2268: char *pList = *ppList;
2269: int nList = *pnList;
2270: char *pEnd = &pList[nList];
2271: int iCurrent = 0;
2272: char *p = pList;
2273:
2274: assert( iCol>=0 );
2275: while( 1 ){
2276: char c = 0;
2277: while( p<pEnd && (c | *p)&0xFE ) c = *p++ & 0x80;
2278:
2279: if( iCol==iCurrent ){
2280: nList = (int)(p - pList);
2281: break;
2282: }
2283:
2284: nList -= (int)(p - pList);
2285: pList = p;
2286: if( nList==0 ){
2287: break;
2288: }
2289: p = &pList[1];
2290: p += sqlite3Fts3GetVarint32(p, &iCurrent);
2291: }
2292:
2293: *ppList = pList;
2294: *pnList = nList;
2295: }
2296:
2297: /*
2298: ** Cache data in the Fts3MultiSegReader.aBuffer[] buffer (overwriting any
2299: ** existing data). Grow the buffer if required.
2300: **
2301: ** If successful, return SQLITE_OK. Otherwise, if an OOM error is encountered
2302: ** trying to resize the buffer, return SQLITE_NOMEM.
2303: */
2304: static int fts3MsrBufferData(
2305: Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */
2306: char *pList,
2307: int nList
2308: ){
2309: if( nList>pMsr->nBuffer ){
2310: char *pNew;
2311: pMsr->nBuffer = nList*2;
2312: pNew = (char *)sqlite3_realloc(pMsr->aBuffer, pMsr->nBuffer);
2313: if( !pNew ) return SQLITE_NOMEM;
2314: pMsr->aBuffer = pNew;
2315: }
2316:
2317: memcpy(pMsr->aBuffer, pList, nList);
2318: return SQLITE_OK;
2319: }
2320:
2321: int sqlite3Fts3MsrIncrNext(
2322: Fts3Table *p, /* Virtual table handle */
2323: Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */
2324: sqlite3_int64 *piDocid, /* OUT: Docid value */
2325: char **paPoslist, /* OUT: Pointer to position list */
2326: int *pnPoslist /* OUT: Size of position list in bytes */
2327: ){
2328: int nMerge = pMsr->nAdvance;
2329: Fts3SegReader **apSegment = pMsr->apSegment;
2330: int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
2331: p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
2332: );
2333:
2334: if( nMerge==0 ){
2335: *paPoslist = 0;
2336: return SQLITE_OK;
2337: }
2338:
2339: while( 1 ){
2340: Fts3SegReader *pSeg;
2341: pSeg = pMsr->apSegment[0];
2342:
2343: if( pSeg->pOffsetList==0 ){
2344: *paPoslist = 0;
2345: break;
2346: }else{
2347: int rc;
2348: char *pList;
2349: int nList;
2350: int j;
2351: sqlite3_int64 iDocid = apSegment[0]->iDocid;
2352:
2353: rc = fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList);
2354: j = 1;
2355: while( rc==SQLITE_OK
2356: && j<nMerge
2357: && apSegment[j]->pOffsetList
2358: && apSegment[j]->iDocid==iDocid
2359: ){
2360: rc = fts3SegReaderNextDocid(p, apSegment[j], 0, 0);
2361: j++;
2362: }
2363: if( rc!=SQLITE_OK ) return rc;
2364: fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp);
2365:
2366: if( pMsr->iColFilter>=0 ){
2367: fts3ColumnFilter(pMsr->iColFilter, &pList, &nList);
2368: }
2369:
2370: if( nList>0 ){
2371: if( fts3SegReaderIsPending(apSegment[0]) ){
2372: rc = fts3MsrBufferData(pMsr, pList, nList+1);
2373: if( rc!=SQLITE_OK ) return rc;
2374: *paPoslist = pMsr->aBuffer;
2375: assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 );
2376: }else{
2377: *paPoslist = pList;
2378: }
2379: *piDocid = iDocid;
2380: *pnPoslist = nList;
2381: break;
2382: }
2383: }
2384: }
2385:
2386: return SQLITE_OK;
2387: }
2388:
2389: static int fts3SegReaderStart(
2390: Fts3Table *p, /* Virtual table handle */
2391: Fts3MultiSegReader *pCsr, /* Cursor object */
2392: const char *zTerm, /* Term searched for (or NULL) */
2393: int nTerm /* Length of zTerm in bytes */
2394: ){
2395: int i;
2396: int nSeg = pCsr->nSegment;
2397:
2398: /* If the Fts3SegFilter defines a specific term (or term prefix) to search
2399: ** for, then advance each segment iterator until it points to a term of
2400: ** equal or greater value than the specified term. This prevents many
2401: ** unnecessary merge/sort operations for the case where single segment
2402: ** b-tree leaf nodes contain more than one term.
2403: */
2404: for(i=0; pCsr->bRestart==0 && i<pCsr->nSegment; i++){
2405: Fts3SegReader *pSeg = pCsr->apSegment[i];
2406: do {
2407: int rc = fts3SegReaderNext(p, pSeg, 0);
2408: if( rc!=SQLITE_OK ) return rc;
2409: }while( zTerm && fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 );
2410: }
2411: fts3SegReaderSort(pCsr->apSegment, nSeg, nSeg, fts3SegReaderCmp);
2412:
2413: return SQLITE_OK;
2414: }
2415:
2416: int sqlite3Fts3SegReaderStart(
2417: Fts3Table *p, /* Virtual table handle */
2418: Fts3MultiSegReader *pCsr, /* Cursor object */
2419: Fts3SegFilter *pFilter /* Restrictions on range of iteration */
2420: ){
2421: pCsr->pFilter = pFilter;
2422: return fts3SegReaderStart(p, pCsr, pFilter->zTerm, pFilter->nTerm);
2423: }
2424:
2425: int sqlite3Fts3MsrIncrStart(
2426: Fts3Table *p, /* Virtual table handle */
2427: Fts3MultiSegReader *pCsr, /* Cursor object */
2428: int iCol, /* Column to match on. */
2429: const char *zTerm, /* Term to iterate through a doclist for */
2430: int nTerm /* Number of bytes in zTerm */
2431: ){
2432: int i;
2433: int rc;
2434: int nSegment = pCsr->nSegment;
2435: int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
2436: p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
2437: );
2438:
2439: assert( pCsr->pFilter==0 );
2440: assert( zTerm && nTerm>0 );
2441:
2442: /* Advance each segment iterator until it points to the term zTerm/nTerm. */
2443: rc = fts3SegReaderStart(p, pCsr, zTerm, nTerm);
2444: if( rc!=SQLITE_OK ) return rc;
2445:
2446: /* Determine how many of the segments actually point to zTerm/nTerm. */
2447: for(i=0; i<nSegment; i++){
2448: Fts3SegReader *pSeg = pCsr->apSegment[i];
2449: if( !pSeg->aNode || fts3SegReaderTermCmp(pSeg, zTerm, nTerm) ){
2450: break;
2451: }
2452: }
2453: pCsr->nAdvance = i;
2454:
2455: /* Advance each of the segments to point to the first docid. */
2456: for(i=0; i<pCsr->nAdvance; i++){
2457: rc = fts3SegReaderFirstDocid(p, pCsr->apSegment[i]);
2458: if( rc!=SQLITE_OK ) return rc;
2459: }
2460: fts3SegReaderSort(pCsr->apSegment, i, i, xCmp);
2461:
2462: assert( iCol<0 || iCol<p->nColumn );
2463: pCsr->iColFilter = iCol;
2464:
2465: return SQLITE_OK;
2466: }
2467:
2468: /*
2469: ** This function is called on a MultiSegReader that has been started using
2470: ** sqlite3Fts3MsrIncrStart(). One or more calls to MsrIncrNext() may also
2471: ** have been made. Calling this function puts the MultiSegReader in such
2472: ** a state that if the next two calls are:
2473: **
2474: ** sqlite3Fts3SegReaderStart()
2475: ** sqlite3Fts3SegReaderStep()
2476: **
2477: ** then the entire doclist for the term is available in
2478: ** MultiSegReader.aDoclist/nDoclist.
2479: */
2480: int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr){
2481: int i; /* Used to iterate through segment-readers */
2482:
2483: assert( pCsr->zTerm==0 );
2484: assert( pCsr->nTerm==0 );
2485: assert( pCsr->aDoclist==0 );
2486: assert( pCsr->nDoclist==0 );
2487:
2488: pCsr->nAdvance = 0;
2489: pCsr->bRestart = 1;
2490: for(i=0; i<pCsr->nSegment; i++){
2491: pCsr->apSegment[i]->pOffsetList = 0;
2492: pCsr->apSegment[i]->nOffsetList = 0;
2493: pCsr->apSegment[i]->iDocid = 0;
2494: }
2495:
2496: return SQLITE_OK;
2497: }
2498:
2499:
2500: int sqlite3Fts3SegReaderStep(
2501: Fts3Table *p, /* Virtual table handle */
2502: Fts3MultiSegReader *pCsr /* Cursor object */
2503: ){
2504: int rc = SQLITE_OK;
2505:
2506: int isIgnoreEmpty = (pCsr->pFilter->flags & FTS3_SEGMENT_IGNORE_EMPTY);
2507: int isRequirePos = (pCsr->pFilter->flags & FTS3_SEGMENT_REQUIRE_POS);
2508: int isColFilter = (pCsr->pFilter->flags & FTS3_SEGMENT_COLUMN_FILTER);
2509: int isPrefix = (pCsr->pFilter->flags & FTS3_SEGMENT_PREFIX);
2510: int isScan = (pCsr->pFilter->flags & FTS3_SEGMENT_SCAN);
2511: int isFirst = (pCsr->pFilter->flags & FTS3_SEGMENT_FIRST);
2512:
2513: Fts3SegReader **apSegment = pCsr->apSegment;
2514: int nSegment = pCsr->nSegment;
2515: Fts3SegFilter *pFilter = pCsr->pFilter;
2516: int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
2517: p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
2518: );
2519:
2520: if( pCsr->nSegment==0 ) return SQLITE_OK;
2521:
2522: do {
2523: int nMerge;
2524: int i;
2525:
2526: /* Advance the first pCsr->nAdvance entries in the apSegment[] array
2527: ** forward. Then sort the list in order of current term again.
2528: */
2529: for(i=0; i<pCsr->nAdvance; i++){
2530: rc = fts3SegReaderNext(p, apSegment[i], 0);
2531: if( rc!=SQLITE_OK ) return rc;
2532: }
2533: fts3SegReaderSort(apSegment, nSegment, pCsr->nAdvance, fts3SegReaderCmp);
2534: pCsr->nAdvance = 0;
2535:
2536: /* If all the seg-readers are at EOF, we're finished. return SQLITE_OK. */
2537: assert( rc==SQLITE_OK );
2538: if( apSegment[0]->aNode==0 ) break;
2539:
2540: pCsr->nTerm = apSegment[0]->nTerm;
2541: pCsr->zTerm = apSegment[0]->zTerm;
2542:
2543: /* If this is a prefix-search, and if the term that apSegment[0] points
2544: ** to does not share a suffix with pFilter->zTerm/nTerm, then all
2545: ** required callbacks have been made. In this case exit early.
2546: **
2547: ** Similarly, if this is a search for an exact match, and the first term
2548: ** of segment apSegment[0] is not a match, exit early.
2549: */
2550: if( pFilter->zTerm && !isScan ){
2551: if( pCsr->nTerm<pFilter->nTerm
2552: || (!isPrefix && pCsr->nTerm>pFilter->nTerm)
2553: || memcmp(pCsr->zTerm, pFilter->zTerm, pFilter->nTerm)
2554: ){
2555: break;
2556: }
2557: }
2558:
2559: nMerge = 1;
2560: while( nMerge<nSegment
2561: && apSegment[nMerge]->aNode
2562: && apSegment[nMerge]->nTerm==pCsr->nTerm
2563: && 0==memcmp(pCsr->zTerm, apSegment[nMerge]->zTerm, pCsr->nTerm)
2564: ){
2565: nMerge++;
2566: }
2567:
2568: assert( isIgnoreEmpty || (isRequirePos && !isColFilter) );
2569: if( nMerge==1
2570: && !isIgnoreEmpty
2571: && !isFirst
2572: && (p->bDescIdx==0 || fts3SegReaderIsPending(apSegment[0])==0)
2573: ){
2574: pCsr->nDoclist = apSegment[0]->nDoclist;
2575: if( fts3SegReaderIsPending(apSegment[0]) ){
2576: rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist, pCsr->nDoclist);
2577: pCsr->aDoclist = pCsr->aBuffer;
2578: }else{
2579: pCsr->aDoclist = apSegment[0]->aDoclist;
2580: }
2581: if( rc==SQLITE_OK ) rc = SQLITE_ROW;
2582: }else{
2583: int nDoclist = 0; /* Size of doclist */
2584: sqlite3_int64 iPrev = 0; /* Previous docid stored in doclist */
2585:
2586: /* The current term of the first nMerge entries in the array
2587: ** of Fts3SegReader objects is the same. The doclists must be merged
2588: ** and a single term returned with the merged doclist.
2589: */
2590: for(i=0; i<nMerge; i++){
2591: fts3SegReaderFirstDocid(p, apSegment[i]);
2592: }
2593: fts3SegReaderSort(apSegment, nMerge, nMerge, xCmp);
2594: while( apSegment[0]->pOffsetList ){
2595: int j; /* Number of segments that share a docid */
2596: char *pList;
2597: int nList;
2598: int nByte;
2599: sqlite3_int64 iDocid = apSegment[0]->iDocid;
2600: fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList);
2601: j = 1;
2602: while( j<nMerge
2603: && apSegment[j]->pOffsetList
2604: && apSegment[j]->iDocid==iDocid
2605: ){
2606: fts3SegReaderNextDocid(p, apSegment[j], 0, 0);
2607: j++;
2608: }
2609:
2610: if( isColFilter ){
2611: fts3ColumnFilter(pFilter->iCol, &pList, &nList);
2612: }
2613:
2614: if( !isIgnoreEmpty || nList>0 ){
2615:
2616: /* Calculate the 'docid' delta value to write into the merged
2617: ** doclist. */
2618: sqlite3_int64 iDelta;
2619: if( p->bDescIdx && nDoclist>0 ){
2620: iDelta = iPrev - iDocid;
2621: }else{
2622: iDelta = iDocid - iPrev;
2623: }
2624: assert( iDelta>0 || (nDoclist==0 && iDelta==iDocid) );
2625: assert( nDoclist>0 || iDelta==iDocid );
2626:
2627: nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);
2628: if( nDoclist+nByte>pCsr->nBuffer ){
2629: char *aNew;
2630: pCsr->nBuffer = (nDoclist+nByte)*2;
2631: aNew = sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer);
2632: if( !aNew ){
2633: return SQLITE_NOMEM;
2634: }
2635: pCsr->aBuffer = aNew;
2636: }
2637:
2638: if( isFirst ){
2639: char *a = &pCsr->aBuffer[nDoclist];
2640: int nWrite;
2641:
2642: nWrite = sqlite3Fts3FirstFilter(iDelta, pList, nList, a);
2643: if( nWrite ){
2644: iPrev = iDocid;
2645: nDoclist += nWrite;
2646: }
2647: }else{
2648: nDoclist += sqlite3Fts3PutVarint(&pCsr->aBuffer[nDoclist], iDelta);
2649: iPrev = iDocid;
2650: if( isRequirePos ){
2651: memcpy(&pCsr->aBuffer[nDoclist], pList, nList);
2652: nDoclist += nList;
2653: pCsr->aBuffer[nDoclist++] = '\0';
2654: }
2655: }
2656: }
2657:
2658: fts3SegReaderSort(apSegment, nMerge, j, xCmp);
2659: }
2660: if( nDoclist>0 ){
2661: pCsr->aDoclist = pCsr->aBuffer;
2662: pCsr->nDoclist = nDoclist;
2663: rc = SQLITE_ROW;
2664: }
2665: }
2666: pCsr->nAdvance = nMerge;
2667: }while( rc==SQLITE_OK );
2668:
2669: return rc;
2670: }
2671:
2672:
2673: void sqlite3Fts3SegReaderFinish(
2674: Fts3MultiSegReader *pCsr /* Cursor object */
2675: ){
2676: if( pCsr ){
2677: int i;
2678: for(i=0; i<pCsr->nSegment; i++){
2679: sqlite3Fts3SegReaderFree(pCsr->apSegment[i]);
2680: }
2681: sqlite3_free(pCsr->apSegment);
2682: sqlite3_free(pCsr->aBuffer);
2683:
2684: pCsr->nSegment = 0;
2685: pCsr->apSegment = 0;
2686: pCsr->aBuffer = 0;
2687: }
2688: }
2689:
2690: /*
2691: ** Merge all level iLevel segments in the database into a single
2692: ** iLevel+1 segment. Or, if iLevel<0, merge all segments into a
2693: ** single segment with a level equal to the numerically largest level
2694: ** currently present in the database.
2695: **
2696: ** If this function is called with iLevel<0, but there is only one
2697: ** segment in the database, SQLITE_DONE is returned immediately.
2698: ** Otherwise, if successful, SQLITE_OK is returned. If an error occurs,
2699: ** an SQLite error code is returned.
2700: */
2701: static int fts3SegmentMerge(Fts3Table *p, int iIndex, int iLevel){
2702: int rc; /* Return code */
2703: int iIdx = 0; /* Index of new segment */
2704: int iNewLevel = 0; /* Level/index to create new segment at */
2705: SegmentWriter *pWriter = 0; /* Used to write the new, merged, segment */
2706: Fts3SegFilter filter; /* Segment term filter condition */
2707: Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */
2708: int bIgnoreEmpty = 0; /* True to ignore empty segments */
2709:
2710: assert( iLevel==FTS3_SEGCURSOR_ALL
2711: || iLevel==FTS3_SEGCURSOR_PENDING
2712: || iLevel>=0
2713: );
2714: assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
2715: assert( iIndex>=0 && iIndex<p->nIndex );
2716:
2717: rc = sqlite3Fts3SegReaderCursor(p, iIndex, iLevel, 0, 0, 1, 0, &csr);
2718: if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished;
2719:
2720: if( iLevel==FTS3_SEGCURSOR_ALL ){
2721: /* This call is to merge all segments in the database to a single
2722: ** segment. The level of the new segment is equal to the the numerically
2723: ** greatest segment level currently present in the database for this
2724: ** index. The idx of the new segment is always 0. */
2725: if( csr.nSegment==1 ){
2726: rc = SQLITE_DONE;
2727: goto finished;
2728: }
2729: rc = fts3SegmentMaxLevel(p, iIndex, &iNewLevel);
2730: bIgnoreEmpty = 1;
2731:
2732: }else if( iLevel==FTS3_SEGCURSOR_PENDING ){
2733: iNewLevel = iIndex * FTS3_SEGDIR_MAXLEVEL;
2734: rc = fts3AllocateSegdirIdx(p, iIndex, 0, &iIdx);
2735: }else{
2736: /* This call is to merge all segments at level iLevel. find the next
2737: ** available segment index at level iLevel+1. The call to
2738: ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to
2739: ** a single iLevel+2 segment if necessary. */
2740: rc = fts3AllocateSegdirIdx(p, iIndex, iLevel+1, &iIdx);
2741: iNewLevel = iIndex * FTS3_SEGDIR_MAXLEVEL + iLevel+1;
2742: }
2743: if( rc!=SQLITE_OK ) goto finished;
2744: assert( csr.nSegment>0 );
2745: assert( iNewLevel>=(iIndex*FTS3_SEGDIR_MAXLEVEL) );
2746: assert( iNewLevel<((iIndex+1)*FTS3_SEGDIR_MAXLEVEL) );
2747:
2748: memset(&filter, 0, sizeof(Fts3SegFilter));
2749: filter.flags = FTS3_SEGMENT_REQUIRE_POS;
2750: filter.flags |= (bIgnoreEmpty ? FTS3_SEGMENT_IGNORE_EMPTY : 0);
2751:
2752: rc = sqlite3Fts3SegReaderStart(p, &csr, &filter);
2753: while( SQLITE_OK==rc ){
2754: rc = sqlite3Fts3SegReaderStep(p, &csr);
2755: if( rc!=SQLITE_ROW ) break;
2756: rc = fts3SegWriterAdd(p, &pWriter, 1,
2757: csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist);
2758: }
2759: if( rc!=SQLITE_OK ) goto finished;
2760: assert( pWriter );
2761:
2762: if( iLevel!=FTS3_SEGCURSOR_PENDING ){
2763: rc = fts3DeleteSegdir(p, iIndex, iLevel, csr.apSegment, csr.nSegment);
2764: if( rc!=SQLITE_OK ) goto finished;
2765: }
2766: rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx);
2767:
2768: finished:
2769: fts3SegWriterFree(pWriter);
2770: sqlite3Fts3SegReaderFinish(&csr);
2771: return rc;
2772: }
2773:
2774:
2775: /*
2776: ** Flush the contents of pendingTerms to level 0 segments.
2777: */
2778: int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
2779: int rc = SQLITE_OK;
2780: int i;
2781: for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
2782: rc = fts3SegmentMerge(p, i, FTS3_SEGCURSOR_PENDING);
2783: if( rc==SQLITE_DONE ) rc = SQLITE_OK;
2784: }
2785: sqlite3Fts3PendingTermsClear(p);
2786: return rc;
2787: }
2788:
2789: /*
2790: ** Encode N integers as varints into a blob.
2791: */
2792: static void fts3EncodeIntArray(
2793: int N, /* The number of integers to encode */
2794: u32 *a, /* The integer values */
2795: char *zBuf, /* Write the BLOB here */
2796: int *pNBuf /* Write number of bytes if zBuf[] used here */
2797: ){
2798: int i, j;
2799: for(i=j=0; i<N; i++){
2800: j += sqlite3Fts3PutVarint(&zBuf[j], (sqlite3_int64)a[i]);
2801: }
2802: *pNBuf = j;
2803: }
2804:
2805: /*
2806: ** Decode a blob of varints into N integers
2807: */
2808: static void fts3DecodeIntArray(
2809: int N, /* The number of integers to decode */
2810: u32 *a, /* Write the integer values */
2811: const char *zBuf, /* The BLOB containing the varints */
2812: int nBuf /* size of the BLOB */
2813: ){
2814: int i, j;
2815: UNUSED_PARAMETER(nBuf);
2816: for(i=j=0; i<N; i++){
2817: sqlite3_int64 x;
2818: j += sqlite3Fts3GetVarint(&zBuf[j], &x);
2819: assert(j<=nBuf);
2820: a[i] = (u32)(x & 0xffffffff);
2821: }
2822: }
2823:
2824: /*
2825: ** Insert the sizes (in tokens) for each column of the document
2826: ** with docid equal to p->iPrevDocid. The sizes are encoded as
2827: ** a blob of varints.
2828: */
2829: static void fts3InsertDocsize(
2830: int *pRC, /* Result code */
2831: Fts3Table *p, /* Table into which to insert */
2832: u32 *aSz /* Sizes of each column, in tokens */
2833: ){
2834: char *pBlob; /* The BLOB encoding of the document size */
2835: int nBlob; /* Number of bytes in the BLOB */
2836: sqlite3_stmt *pStmt; /* Statement used to insert the encoding */
2837: int rc; /* Result code from subfunctions */
2838:
2839: if( *pRC ) return;
2840: pBlob = sqlite3_malloc( 10*p->nColumn );
2841: if( pBlob==0 ){
2842: *pRC = SQLITE_NOMEM;
2843: return;
2844: }
2845: fts3EncodeIntArray(p->nColumn, aSz, pBlob, &nBlob);
2846: rc = fts3SqlStmt(p, SQL_REPLACE_DOCSIZE, &pStmt, 0);
2847: if( rc ){
2848: sqlite3_free(pBlob);
2849: *pRC = rc;
2850: return;
2851: }
2852: sqlite3_bind_int64(pStmt, 1, p->iPrevDocid);
2853: sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, sqlite3_free);
2854: sqlite3_step(pStmt);
2855: *pRC = sqlite3_reset(pStmt);
2856: }
2857:
2858: /*
2859: ** Record 0 of the %_stat table contains a blob consisting of N varints,
2860: ** where N is the number of user defined columns in the fts3 table plus
2861: ** two. If nCol is the number of user defined columns, then values of the
2862: ** varints are set as follows:
2863: **
2864: ** Varint 0: Total number of rows in the table.
2865: **
2866: ** Varint 1..nCol: For each column, the total number of tokens stored in
2867: ** the column for all rows of the table.
2868: **
2869: ** Varint 1+nCol: The total size, in bytes, of all text values in all
2870: ** columns of all rows of the table.
2871: **
2872: */
2873: static void fts3UpdateDocTotals(
2874: int *pRC, /* The result code */
2875: Fts3Table *p, /* Table being updated */
2876: u32 *aSzIns, /* Size increases */
2877: u32 *aSzDel, /* Size decreases */
2878: int nChng /* Change in the number of documents */
2879: ){
2880: char *pBlob; /* Storage for BLOB written into %_stat */
2881: int nBlob; /* Size of BLOB written into %_stat */
2882: u32 *a; /* Array of integers that becomes the BLOB */
2883: sqlite3_stmt *pStmt; /* Statement for reading and writing */
2884: int i; /* Loop counter */
2885: int rc; /* Result code from subfunctions */
2886:
2887: const int nStat = p->nColumn+2;
2888:
2889: if( *pRC ) return;
2890: a = sqlite3_malloc( (sizeof(u32)+10)*nStat );
2891: if( a==0 ){
2892: *pRC = SQLITE_NOMEM;
2893: return;
2894: }
2895: pBlob = (char*)&a[nStat];
2896: rc = fts3SqlStmt(p, SQL_SELECT_DOCTOTAL, &pStmt, 0);
2897: if( rc ){
2898: sqlite3_free(a);
2899: *pRC = rc;
2900: return;
2901: }
2902: if( sqlite3_step(pStmt)==SQLITE_ROW ){
2903: fts3DecodeIntArray(nStat, a,
2904: sqlite3_column_blob(pStmt, 0),
2905: sqlite3_column_bytes(pStmt, 0));
2906: }else{
2907: memset(a, 0, sizeof(u32)*(nStat) );
2908: }
2909: sqlite3_reset(pStmt);
2910: if( nChng<0 && a[0]<(u32)(-nChng) ){
2911: a[0] = 0;
2912: }else{
2913: a[0] += nChng;
2914: }
2915: for(i=0; i<p->nColumn+1; i++){
2916: u32 x = a[i+1];
2917: if( x+aSzIns[i] < aSzDel[i] ){
2918: x = 0;
2919: }else{
2920: x = x + aSzIns[i] - aSzDel[i];
2921: }
2922: a[i+1] = x;
2923: }
2924: fts3EncodeIntArray(nStat, a, pBlob, &nBlob);
2925: rc = fts3SqlStmt(p, SQL_REPLACE_DOCTOTAL, &pStmt, 0);
2926: if( rc ){
2927: sqlite3_free(a);
2928: *pRC = rc;
2929: return;
2930: }
2931: sqlite3_bind_blob(pStmt, 1, pBlob, nBlob, SQLITE_STATIC);
2932: sqlite3_step(pStmt);
2933: *pRC = sqlite3_reset(pStmt);
2934: sqlite3_free(a);
2935: }
2936:
2937: static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
2938: int i;
2939: int bSeenDone = 0;
2940: int rc = SQLITE_OK;
2941: for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
2942: rc = fts3SegmentMerge(p, i, FTS3_SEGCURSOR_ALL);
2943: if( rc==SQLITE_DONE ){
2944: bSeenDone = 1;
2945: rc = SQLITE_OK;
2946: }
2947: }
2948: sqlite3Fts3SegmentsClose(p);
2949: sqlite3Fts3PendingTermsClear(p);
2950:
2951: return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc;
2952: }
2953:
2954: /*
2955: ** This function is called when the user executes the following statement:
2956: **
2957: ** INSERT INTO <tbl>(<tbl>) VALUES('rebuild');
2958: **
2959: ** The entire FTS index is discarded and rebuilt. If the table is one
2960: ** created using the content=xxx option, then the new index is based on
2961: ** the current contents of the xxx table. Otherwise, it is rebuilt based
2962: ** on the contents of the %_content table.
2963: */
2964: static int fts3DoRebuild(Fts3Table *p){
2965: int rc; /* Return Code */
2966:
2967: rc = fts3DeleteAll(p, 0);
2968: if( rc==SQLITE_OK ){
2969: u32 *aSz = 0;
2970: u32 *aSzIns = 0;
2971: u32 *aSzDel = 0;
2972: sqlite3_stmt *pStmt = 0;
2973: int nEntry = 0;
2974:
2975: /* Compose and prepare an SQL statement to loop through the content table */
2976: char *zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist);
2977: if( !zSql ){
2978: rc = SQLITE_NOMEM;
2979: }else{
2980: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
2981: sqlite3_free(zSql);
2982: }
2983:
2984: if( rc==SQLITE_OK ){
2985: int nByte = sizeof(u32) * (p->nColumn+1)*3;
2986: aSz = (u32 *)sqlite3_malloc(nByte);
2987: if( aSz==0 ){
2988: rc = SQLITE_NOMEM;
2989: }else{
2990: memset(aSz, 0, nByte);
2991: aSzIns = &aSz[p->nColumn+1];
2992: aSzDel = &aSzIns[p->nColumn+1];
2993: }
2994: }
2995:
2996: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
2997: int iCol;
2998: rc = fts3PendingTermsDocid(p, sqlite3_column_int64(pStmt, 0));
2999: aSz[p->nColumn] = 0;
3000: for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
3001: const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
3002: rc = fts3PendingTermsAdd(p, z, iCol, &aSz[iCol]);
3003: aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1);
3004: }
3005: if( p->bHasDocsize ){
3006: fts3InsertDocsize(&rc, p, aSz);
3007: }
3008: if( rc!=SQLITE_OK ){
3009: sqlite3_finalize(pStmt);
3010: pStmt = 0;
3011: }else{
3012: nEntry++;
3013: for(iCol=0; iCol<=p->nColumn; iCol++){
3014: aSzIns[iCol] += aSz[iCol];
3015: }
3016: }
3017: }
3018: if( p->bHasStat ){
3019: fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nEntry);
3020: }
3021: sqlite3_free(aSz);
3022:
3023: if( pStmt ){
3024: int rc2 = sqlite3_finalize(pStmt);
3025: if( rc==SQLITE_OK ){
3026: rc = rc2;
3027: }
3028: }
3029: }
3030:
3031: return rc;
3032: }
3033:
3034: /*
3035: ** Handle a 'special' INSERT of the form:
3036: **
3037: ** "INSERT INTO tbl(tbl) VALUES(<expr>)"
3038: **
3039: ** Argument pVal contains the result of <expr>. Currently the only
3040: ** meaningful value to insert is the text 'optimize'.
3041: */
3042: static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
3043: int rc; /* Return Code */
3044: const char *zVal = (const char *)sqlite3_value_text(pVal);
3045: int nVal = sqlite3_value_bytes(pVal);
3046:
3047: if( !zVal ){
3048: return SQLITE_NOMEM;
3049: }else if( nVal==8 && 0==sqlite3_strnicmp(zVal, "optimize", 8) ){
3050: rc = fts3DoOptimize(p, 0);
3051: }else if( nVal==7 && 0==sqlite3_strnicmp(zVal, "rebuild", 7) ){
3052: rc = fts3DoRebuild(p);
3053: #ifdef SQLITE_TEST
3054: }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
3055: p->nNodeSize = atoi(&zVal[9]);
3056: rc = SQLITE_OK;
3057: }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
3058: p->nMaxPendingData = atoi(&zVal[11]);
3059: rc = SQLITE_OK;
3060: #endif
3061: }else{
3062: rc = SQLITE_ERROR;
3063: }
3064:
3065: return rc;
3066: }
3067:
3068: /*
3069: ** Delete all cached deferred doclists. Deferred doclists are cached
3070: ** (allocated) by the sqlite3Fts3CacheDeferredDoclists() function.
3071: */
3072: void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *pCsr){
3073: Fts3DeferredToken *pDef;
3074: for(pDef=pCsr->pDeferred; pDef; pDef=pDef->pNext){
3075: fts3PendingListDelete(pDef->pList);
3076: pDef->pList = 0;
3077: }
3078: }
3079:
3080: /*
3081: ** Free all entries in the pCsr->pDeffered list. Entries are added to
3082: ** this list using sqlite3Fts3DeferToken().
3083: */
3084: void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *pCsr){
3085: Fts3DeferredToken *pDef;
3086: Fts3DeferredToken *pNext;
3087: for(pDef=pCsr->pDeferred; pDef; pDef=pNext){
3088: pNext = pDef->pNext;
3089: fts3PendingListDelete(pDef->pList);
3090: sqlite3_free(pDef);
3091: }
3092: pCsr->pDeferred = 0;
3093: }
3094:
3095: /*
3096: ** Generate deferred-doclists for all tokens in the pCsr->pDeferred list
3097: ** based on the row that pCsr currently points to.
3098: **
3099: ** A deferred-doclist is like any other doclist with position information
3100: ** included, except that it only contains entries for a single row of the
3101: ** table, not for all rows.
3102: */
3103: int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *pCsr){
3104: int rc = SQLITE_OK; /* Return code */
3105: if( pCsr->pDeferred ){
3106: int i; /* Used to iterate through table columns */
3107: sqlite3_int64 iDocid; /* Docid of the row pCsr points to */
3108: Fts3DeferredToken *pDef; /* Used to iterate through deferred tokens */
3109:
3110: Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
3111: sqlite3_tokenizer *pT = p->pTokenizer;
3112: sqlite3_tokenizer_module const *pModule = pT->pModule;
3113:
3114: assert( pCsr->isRequireSeek==0 );
3115: iDocid = sqlite3_column_int64(pCsr->pStmt, 0);
3116:
3117: for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){
3118: const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1);
3119: sqlite3_tokenizer_cursor *pTC = 0;
3120:
3121: rc = pModule->xOpen(pT, zText, -1, &pTC);
3122: while( rc==SQLITE_OK ){
3123: char const *zToken; /* Buffer containing token */
3124: int nToken; /* Number of bytes in token */
3125: int iDum1, iDum2; /* Dummy variables */
3126: int iPos; /* Position of token in zText */
3127:
3128: pTC->pTokenizer = pT;
3129: rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
3130: for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
3131: Fts3PhraseToken *pPT = pDef->pToken;
3132: if( (pDef->iCol>=p->nColumn || pDef->iCol==i)
3133: && (pPT->bFirst==0 || iPos==0)
3134: && (pPT->n==nToken || (pPT->isPrefix && pPT->n<nToken))
3135: && (0==memcmp(zToken, pPT->z, pPT->n))
3136: ){
3137: fts3PendingListAppend(&pDef->pList, iDocid, i, iPos, &rc);
3138: }
3139: }
3140: }
3141: if( pTC ) pModule->xClose(pTC);
3142: if( rc==SQLITE_DONE ) rc = SQLITE_OK;
3143: }
3144:
3145: for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
3146: if( pDef->pList ){
3147: rc = fts3PendingListAppendVarint(&pDef->pList, 0);
3148: }
3149: }
3150: }
3151:
3152: return rc;
3153: }
3154:
3155: int sqlite3Fts3DeferredTokenList(
3156: Fts3DeferredToken *p,
3157: char **ppData,
3158: int *pnData
3159: ){
3160: char *pRet;
3161: int nSkip;
3162: sqlite3_int64 dummy;
3163:
3164: *ppData = 0;
3165: *pnData = 0;
3166:
3167: if( p->pList==0 ){
3168: return SQLITE_OK;
3169: }
3170:
3171: pRet = (char *)sqlite3_malloc(p->pList->nData);
3172: if( !pRet ) return SQLITE_NOMEM;
3173:
3174: nSkip = sqlite3Fts3GetVarint(p->pList->aData, &dummy);
3175: *pnData = p->pList->nData - nSkip;
3176: *ppData = pRet;
3177:
3178: memcpy(pRet, &p->pList->aData[nSkip], *pnData);
3179: return SQLITE_OK;
3180: }
3181:
3182: /*
3183: ** Add an entry for token pToken to the pCsr->pDeferred list.
3184: */
3185: int sqlite3Fts3DeferToken(
3186: Fts3Cursor *pCsr, /* Fts3 table cursor */
3187: Fts3PhraseToken *pToken, /* Token to defer */
3188: int iCol /* Column that token must appear in (or -1) */
3189: ){
3190: Fts3DeferredToken *pDeferred;
3191: pDeferred = sqlite3_malloc(sizeof(*pDeferred));
3192: if( !pDeferred ){
3193: return SQLITE_NOMEM;
3194: }
3195: memset(pDeferred, 0, sizeof(*pDeferred));
3196: pDeferred->pToken = pToken;
3197: pDeferred->pNext = pCsr->pDeferred;
3198: pDeferred->iCol = iCol;
3199: pCsr->pDeferred = pDeferred;
3200:
3201: assert( pToken->pDeferred==0 );
3202: pToken->pDeferred = pDeferred;
3203:
3204: return SQLITE_OK;
3205: }
3206:
3207: /*
3208: ** SQLite value pRowid contains the rowid of a row that may or may not be
3209: ** present in the FTS3 table. If it is, delete it and adjust the contents
3210: ** of subsiduary data structures accordingly.
3211: */
3212: static int fts3DeleteByRowid(
3213: Fts3Table *p,
3214: sqlite3_value *pRowid,
3215: int *pnDoc,
3216: u32 *aSzDel
3217: ){
3218: int isEmpty = 0;
3219: int rc = fts3IsEmpty(p, pRowid, &isEmpty);
3220: if( rc==SQLITE_OK ){
3221: if( isEmpty ){
3222: /* Deleting this row means the whole table is empty. In this case
3223: ** delete the contents of all three tables and throw away any
3224: ** data in the pendingTerms hash table. */
3225: rc = fts3DeleteAll(p, 1);
3226: *pnDoc = *pnDoc - 1;
3227: }else{
3228: sqlite3_int64 iRemove = sqlite3_value_int64(pRowid);
3229: rc = fts3PendingTermsDocid(p, iRemove);
3230: fts3DeleteTerms(&rc, p, pRowid, aSzDel);
3231: if( p->zContentTbl==0 ){
3232: fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid);
3233: if( sqlite3_changes(p->db) ) *pnDoc = *pnDoc - 1;
3234: }else{
3235: *pnDoc = *pnDoc - 1;
3236: }
3237: if( p->bHasDocsize ){
3238: fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid);
3239: }
3240: }
3241: }
3242:
3243: return rc;
3244: }
3245:
3246: /*
3247: ** This function does the work for the xUpdate method of FTS3 virtual
3248: ** tables.
3249: */
3250: int sqlite3Fts3UpdateMethod(
3251: sqlite3_vtab *pVtab, /* FTS3 vtab object */
3252: int nArg, /* Size of argument array */
3253: sqlite3_value **apVal, /* Array of arguments */
3254: sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */
3255: ){
3256: Fts3Table *p = (Fts3Table *)pVtab;
3257: int rc = SQLITE_OK; /* Return Code */
3258: int isRemove = 0; /* True for an UPDATE or DELETE */
3259: u32 *aSzIns = 0; /* Sizes of inserted documents */
3260: u32 *aSzDel; /* Sizes of deleted documents */
3261: int nChng = 0; /* Net change in number of documents */
3262: int bInsertDone = 0;
3263:
3264: assert( p->pSegments==0 );
3265:
3266: /* Check for a "special" INSERT operation. One of the form:
3267: **
3268: ** INSERT INTO xyz(xyz) VALUES('command');
3269: */
3270: if( nArg>1
3271: && sqlite3_value_type(apVal[0])==SQLITE_NULL
3272: && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL
3273: ){
3274: rc = fts3SpecialInsert(p, apVal[p->nColumn+2]);
3275: goto update_out;
3276: }
3277:
3278: /* Allocate space to hold the change in document sizes */
3279: aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 );
3280: if( aSzIns==0 ){
3281: rc = SQLITE_NOMEM;
3282: goto update_out;
3283: }
3284: aSzDel = &aSzIns[p->nColumn+1];
3285: memset(aSzIns, 0, sizeof(aSzIns[0])*(p->nColumn+1)*2);
3286:
3287: /* If this is an INSERT operation, or an UPDATE that modifies the rowid
3288: ** value, then this operation requires constraint handling.
3289: **
3290: ** If the on-conflict mode is REPLACE, this means that the existing row
3291: ** should be deleted from the database before inserting the new row. Or,
3292: ** if the on-conflict mode is other than REPLACE, then this method must
3293: ** detect the conflict and return SQLITE_CONSTRAINT before beginning to
3294: ** modify the database file.
3295: */
3296: if( nArg>1 && p->zContentTbl==0 ){
3297: /* Find the value object that holds the new rowid value. */
3298: sqlite3_value *pNewRowid = apVal[3+p->nColumn];
3299: if( sqlite3_value_type(pNewRowid)==SQLITE_NULL ){
3300: pNewRowid = apVal[1];
3301: }
3302:
3303: if( sqlite3_value_type(pNewRowid)!=SQLITE_NULL && (
3304: sqlite3_value_type(apVal[0])==SQLITE_NULL
3305: || sqlite3_value_int64(apVal[0])!=sqlite3_value_int64(pNewRowid)
3306: )){
3307: /* The new rowid is not NULL (in this case the rowid will be
3308: ** automatically assigned and there is no chance of a conflict), and
3309: ** the statement is either an INSERT or an UPDATE that modifies the
3310: ** rowid column. So if the conflict mode is REPLACE, then delete any
3311: ** existing row with rowid=pNewRowid.
3312: **
3313: ** Or, if the conflict mode is not REPLACE, insert the new record into
3314: ** the %_content table. If we hit the duplicate rowid constraint (or any
3315: ** other error) while doing so, return immediately.
3316: **
3317: ** This branch may also run if pNewRowid contains a value that cannot
3318: ** be losslessly converted to an integer. In this case, the eventual
3319: ** call to fts3InsertData() (either just below or further on in this
3320: ** function) will return SQLITE_MISMATCH. If fts3DeleteByRowid is
3321: ** invoked, it will delete zero rows (since no row will have
3322: ** docid=$pNewRowid if $pNewRowid is not an integer value).
3323: */
3324: if( sqlite3_vtab_on_conflict(p->db)==SQLITE_REPLACE ){
3325: rc = fts3DeleteByRowid(p, pNewRowid, &nChng, aSzDel);
3326: }else{
3327: rc = fts3InsertData(p, apVal, pRowid);
3328: bInsertDone = 1;
3329: }
3330: }
3331: }
3332: if( rc!=SQLITE_OK ){
3333: goto update_out;
3334: }
3335:
3336: /* If this is a DELETE or UPDATE operation, remove the old record. */
3337: if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
3338: assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER );
3339: rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel);
3340: isRemove = 1;
3341: }
3342:
3343: /* If this is an INSERT or UPDATE operation, insert the new record. */
3344: if( nArg>1 && rc==SQLITE_OK ){
3345: if( bInsertDone==0 ){
3346: rc = fts3InsertData(p, apVal, pRowid);
3347: if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){
3348: rc = FTS_CORRUPT_VTAB;
3349: }
3350: }
3351: if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){
3352: rc = fts3PendingTermsDocid(p, *pRowid);
3353: }
3354: if( rc==SQLITE_OK ){
3355: assert( p->iPrevDocid==*pRowid );
3356: rc = fts3InsertTerms(p, apVal, aSzIns);
3357: }
3358: if( p->bHasDocsize ){
3359: fts3InsertDocsize(&rc, p, aSzIns);
3360: }
3361: nChng++;
3362: }
3363:
3364: if( p->bHasStat ){
3365: fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng);
3366: }
3367:
3368: update_out:
3369: sqlite3_free(aSzIns);
3370: sqlite3Fts3SegmentsClose(p);
3371: return rc;
3372: }
3373:
3374: /*
3375: ** Flush any data in the pending-terms hash table to disk. If successful,
3376: ** merge all segments in the database (including the new segment, if
3377: ** there was any data to flush) into a single segment.
3378: */
3379: int sqlite3Fts3Optimize(Fts3Table *p){
3380: int rc;
3381: rc = sqlite3_exec(p->db, "SAVEPOINT fts3", 0, 0, 0);
3382: if( rc==SQLITE_OK ){
3383: rc = fts3DoOptimize(p, 1);
3384: if( rc==SQLITE_OK || rc==SQLITE_DONE ){
3385: int rc2 = sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0);
3386: if( rc2!=SQLITE_OK ) rc = rc2;
3387: }else{
3388: sqlite3_exec(p->db, "ROLLBACK TO fts3", 0, 0, 0);
3389: sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0);
3390: }
3391: }
3392: sqlite3Fts3SegmentsClose(p);
3393: return rc;
3394: }
3395:
3396: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>