}
}
-
-static Fts3Table *cursor_vtab(Fts3Cursor *c){
- return (Fts3Table *) c->base.pVtab;
-}
-
/*
** The xDisconnect() virtual table method.
*/
int nDb;
int nName;
+#ifdef SQLITE_TEST
+ char *zTestParam = 0;
+ if( strncmp(argv[argc-1], "test:", 5)==0 ){
+ zTestParam = argv[argc-1];
+ argc--;
+ }
+#endif
+
const char *zTokenizer = 0; /* Name of tokenizer to use */
sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */
p->nPendingData = 0;
p->azColumn = (char **)&p[1];
p->pTokenizer = pTokenizer;
+ p->nNodeSize = 1000;
zCsr = (char *)&p->azColumn[nCol];
fts3HashInit(&p->pendingTerms, FTS3_HASH_STRING, 1);
rc = fts3DeclareVtab(p);
if( rc!=SQLITE_OK ) goto fts3_init_out;
+#ifdef SQLITE_TEST
+ if( zTestParam ){
+ p->nNodeSize = atoi(&zTestParam[5]);
+ }
+#endif
*ppVTab = &p->base;
fts3_init_out:
return rc;
}
+/*
+** This function is used to create delta-encoded serialized lists of FTS3
+** varints. Each call to this function appends a single varint to a list.
+*/
static void fts3PutDeltaVarint(
- char **pp,
- sqlite3_int64 *piPrev,
- sqlite3_int64 iVal
+ char **pp, /* IN/OUT: Output pointer */
+ sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */
+ sqlite3_int64 iVal /* Write this value to the list */
){
- assert( iVal-*piPrev > 0 );
+ assert( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) );
*pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev);
*piPrev = iVal;
}
sqlite3_int64 i2 = sqlite3_column_int64(pStmt, 2);
rc = sqlite3Fts3SegReaderNew(p, iAge, i1, i2, 0, 0, 0, &pNew);
}
+ sqlite3Fts3ReadBlock(p, 0, 0, 0);
}
iAge++;
if( SQLITE_OK==(rc = evalFts3Expr(p, pExpr->pRight, &aRight, &nRight))
&& SQLITE_OK==(rc = evalFts3Expr(p, pExpr->pLeft, &aLeft, &nLeft))
){
+ assert( pExpr->eType==FTSQUERY_NEAR || pExpr->eType==FTSQUERY_OR
+ || pExpr->eType==FTSQUERY_AND || pExpr->eType==FTSQUERY_NOT
+ );
switch( pExpr->eType ){
case FTSQUERY_NEAR: {
Fts3Expr *pLeft;
break;
}
- case FTSQUERY_AND:
- case FTSQUERY_NOT: {
+ default: {
assert( FTSQUERY_NOT==MERGE_NOT && FTSQUERY_AND==MERGE_AND );
fts3DoclistMerge(pExpr->eType, 0, 0, aLeft, pnOut,
aLeft, nLeft, aRight, nRight
return ((Fts3Cursor *)pCursor)->isEof;
}
-/*
-** This is the xColumn method of the virtual table. The SQLite
-** core calls this method during a query when it needs the value
-** of a column from the virtual table. This method needs to use
-** one of the sqlite3_result_*() routines to store the requested
-** value back in the pContext.
-*/
-static int fts3ColumnMethod(sqlite3_vtab_cursor *pCursor,
- sqlite3_context *pContext, int idxCol){
- Fts3Cursor *c = (Fts3Cursor *) pCursor;
- Fts3Table *v = cursor_vtab(c);
- int rc = fts3CursorSeek(c);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- if( idxCol<v->nColumn ){
- sqlite3_value *pVal = sqlite3_column_value(c->pStmt, idxCol+1);
- sqlite3_result_value(pContext, pVal);
- }else if( idxCol==v->nColumn ){
- /* The extra column whose name is the same as the table.
- ** Return a blob which is a pointer to the cursor
- */
- sqlite3_result_blob(pContext, &c, sizeof(c), SQLITE_TRANSIENT);
- }else if( idxCol==v->nColumn+1 ){
- /* The docid column, which is an alias for rowid. */
- sqlite3_value *pVal = sqlite3_column_value(c->pStmt, 0);
- sqlite3_result_value(pContext, pVal);
- }
- return SQLITE_OK;
-}
-
/*
** This is the xRowid method. The SQLite core calls this routine to
** retrieve the rowid for the current row of the result set. fts3
return SQLITE_OK;
}
+/*
+** This is the xColumn method, called by SQLite to request a value from
+** the row that the supplied cursor currently points to.
+*/
+static int fts3ColumnMethod(
+ sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
+ sqlite3_context *pContext, /* Context for sqlite3_result_xxx() calls */
+ int iCol /* Index of column to read value from */
+){
+ int rc; /* Return Code */
+ Fts3Cursor *pCsr = (Fts3Cursor *) pCursor;
+ Fts3Table *p = (Fts3Table *)pCursor->pVtab;
+
+ /* The column value supplied by SQLite must be in range. */
+ assert( iCol>=0 && iCol<=p->nColumn+1 );
+
+ rc = fts3CursorSeek(pCsr);
+ if( rc==SQLITE_OK ){
+ if( iCol==p->nColumn+1 ){
+ /* This call is a request for the "docid" column. Since "docid" is an
+ ** alias for "rowid", use the xRowid() method to obtain the value.
+ */
+ sqlite3_int64 iRowid;
+ rc = fts3RowidMethod(pCursor, &iRowid);
+ sqlite3_result_int64(pContext, iRowid);
+ }else if( iCol==p->nColumn ){
+ /* The extra column whose name is the same as the table.
+ ** Return a blob which is a pointer to the cursor.
+ */
+ sqlite3_result_blob(pContext, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
+ }else{
+ sqlite3_result_value(pContext, sqlite3_column_value(pCsr->pStmt, iCol+1));
+ }
+ }
+ return rc;
+}
+
/*
** This function is the implementation of the xUpdate callback used by
** FTS3 virtual tables. It is invoked by SQLite each time a row is to be
int nLeavesAlloc; /* Allocated size of aLeavesStmt */
sqlite3_stmt **aLeavesStmt; /* Array of prepared zSelectLeaves stmts */
+ int nNodeSize; /* Soft limit for node size */
+
/* The following hash table is used to buffer pending index updates during
** transactions. Variable nPendingData estimates the memory size of the
** pending data, including hash table overhead, but not malloc overhead.
#include <assert.h>
#include <stdlib.h>
-#define INTERIOR_MAX 2048 /* Soft limit for segment node size */
-#define LEAF_MAX 2048 /* Soft limit for segment leaf size */
-
typedef struct PendingList PendingList;
typedef struct SegmentNode SegmentNode;
typedef struct SegmentWriter SegmentWriter;
if( rc!=SQLITE_OK ) return rc;
sqlite3_reset(pStmt);
- sqlite3_bind_int64(pStmt, 1, iBlock);
- rc = sqlite3_step(pStmt);
- if( rc!=SQLITE_ROW ){
- return SQLITE_CORRUPT;
- }
-
- *pnBlock = sqlite3_column_bytes(pStmt, 0);
- *pzBlock = (char *)sqlite3_column_blob(pStmt, 0);
- if( !*pzBlock ){
- return SQLITE_NOMEM;
+ if( pzBlock ){
+ sqlite3_bind_int64(pStmt, 1, iBlock);
+ rc = sqlite3_step(pStmt);
+ if( rc!=SQLITE_ROW ){
+ return SQLITE_CORRUPT;
+ }
+
+ *pnBlock = sqlite3_column_bytes(pStmt, 0);
+ *pzBlock = (char *)sqlite3_column_blob(pStmt, 0);
+ if( !*pzBlock ){
+ return SQLITE_NOMEM;
+ }
}
return SQLITE_OK;
}
nSuffix = nTerm-nPrefix;
nReq += sqlite3Fts3VarintLen(nPrefix)+sqlite3Fts3VarintLen(nSuffix)+nSuffix;
- if( nReq<=INTERIOR_MAX || !pTree->zTerm ){
+ if( nReq<=p->nNodeSize || !pTree->zTerm ){
- if( nReq>INTERIOR_MAX ){
+ if( nReq>p->nNodeSize ){
/* An unusual case: this is the first term to be added to the node
- ** and the static node buffer (INTERIOR_MAX bytes) is not large
+ ** and the static node buffer (p->nNodeSize bytes) is not large
** enough. Use a separately malloced buffer instead This wastes
- ** INTERIOR_MAX bytes, but since this scenario only comes about when
+ ** p->nNodeSize bytes, but since this scenario only comes about when
** the database contain two terms that share a prefix of almost 2KB,
** this is not expected to be a serious problem.
*/
** now. Instead, the term is inserted into the parent of pTree. If pTree
** has no parent, one is created here.
*/
- pNew = (SegmentNode *)sqlite3_malloc(sizeof(SegmentNode) + INTERIOR_MAX);
+ pNew = (SegmentNode *)sqlite3_malloc(sizeof(SegmentNode) + p->nNodeSize);
if( !pNew ){
return SQLITE_NOMEM;
}
*ppWriter = pWriter;
/* Allocate a buffer in which to accumulate data */
- pWriter->aData = (char *)sqlite3_malloc(LEAF_MAX);
+ pWriter->aData = (char *)sqlite3_malloc(p->nNodeSize);
if( !pWriter->aData ) return SQLITE_NOMEM;
- pWriter->nSize = LEAF_MAX;
+ pWriter->nSize = p->nNodeSize;
/* Find the next free blockid in the %_segments table */
rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pStmt, 0);
sqlite3Fts3VarintLen(nDoclist) + /* Size of doclist */
nDoclist; /* Doclist data */
- if( nData>0 && nData+nReq>LEAF_MAX ){
+ if( nData>0 && nData+nReq>p->nNodeSize ){
int rc;
/* The current leaf node is full. Write it out to the database. */
-C Updates\sto\sFTS3\sto\scorrect\scompiler\swarnings\sunder\sMSVC.
-D 2009-12-03T06:26:46
+C Fix\san\sincorrect\sassert()\sin\sfts3.c.\sAdd\sfurther\sfts3\stests.
+D 2009-12-03T17:36:22
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in c5827ead754ab32b9585487177c93bb00b9497b3
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers 998756696647400de63d5ba60e9655036cb966e9
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
-F ext/fts3/fts3.c 8352dc3506c3b30fde126ea5da9c431d3c243522
+F ext/fts3/fts3.c b15d44a46f76b08806b75d70c44c62254269d619
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
-F ext/fts3/fts3Int.h 515132f0ae6b35eccbeef72a2bafb16d7e251953
+F ext/fts3/fts3Int.h cc716c74afa7da8e0f8ef39404f33ea62a823eb3
F ext/fts3/fts3_expr.c c18794a62c257d3456d3314c5a18e348ae0d84bd
F ext/fts3/fts3_hash.c 18feef38fca216992725e9eae775a0c7735e6724
F ext/fts3/fts3_hash.h d410ff2c93c81a56b927fcf07b2099ccbfa7a479
F ext/fts3/fts3_tokenizer.c 73a4e0e068720153901622f215298b73e7c976c7
F ext/fts3/fts3_tokenizer.h 7ff73caa3327589bf6550f60d93ebdd1f6a0fb5c
F ext/fts3/fts3_tokenizer1.c 11a604a53cff5e8c28882727bf794e5252e5227b
-F ext/fts3/fts3_write.c 6c59b1d6eed759815151298c132d79301c205fce
+F ext/fts3/fts3_write.c ec51fb6886f910e78ae32158ec0301aa675f52d8
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/icu/README.txt 3b130aa66e7a681136f6add198b076a2f90d1e33
F ext/icu/icu.c 12e763d288d23b5a49de37caa30737b971a2f1e2
F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
F test/fts3expr.test 05dab77387801e4900009917bb18f556037d82da
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
-F test/fts3malloc.test efbd316eafe54471b7f68604c050418b31d1914e
+F test/fts3malloc.test d02ee86b21edd2b43044e0d6dfdcd26cb6efddcb
F test/fts3near.test dc196dd17b4606f440c580d45b3d23aa975fd077
+F test/fts3rnd.test bbb85c6b2b55f15a8ecaaf1585a94845501f7369
F test/func.test af106ed834001738246d276659406823e35cde7b
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
F test/fuzz.test a4174c3009a3e2c2e14b31b364ebf7ddb49de2c9
F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea
F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
-F test/quick.test 12fdc7656b4d20a537a686fb223eb99b5fe54483
+F test/quick.test 31d0c41d1602af5a2b402682770943b77d42d309
F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
F test/randexpr1.test 1084050991e9ba22c1c10edd8d84673b501cc25a
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P e3aa0870fce0666bf8c67ad6ec23e135d03b604a
-R 8d9ad89e2fac8a1d1d94a1d048213789
-U shaneh
-Z 7667ec8a886e15725b2ab6f5b341cdfd
+P 37495b55ffbdc2db4482367ac7d8e32d4d71d58e
+R cfd8087616225b6f440fa1c8b43bd349
+U dan
+Z bf00a60fa922c646641246a97c22e493
-37495b55ffbdc2db4482367ac7d8e32d4d71d58e
\ No newline at end of file
+75863c2d55e0801add5b8dcf88d575c5c870af04
\ No newline at end of file
#
#
-#-------------------------------------------------------------------------
-# This proc is used to test a single SELECT statement. Parameter $name is
-# passed a name for the test case (i.e. "fts3_malloc-1.4.1") and parameter
-# $sql is passed the text of the SELECT statement. Parameter $result is
-# set to the expected output if the SELECT statement is successfully
-# executed using [db eval].
-#
-# Example:
-#
-# do_select_test testcase-1.1 "SELECT 1+1, 1+2" {1 2}
-#
-# If global variable DO_MALLOC_TEST is set to a non-zero value, or if
-# it is not defined at all, then OOM testing is performed on the SELECT
-# statement. Each OOM test case is said to pass if either (a) executing
-# the SELECT statement succeeds and the results match those specified
-# by parameter $result, or (b) TCL throws an "out of memory" error.
-#
-# If DO_MALLOC_TEST is defined and set to zero, then the SELECT statement
-# is executed just once. In this case the test case passes if the results
-# match the expected results passed via parameter $result.
-#
-proc do_select_test {name sql result} {
- doPassiveTest $name $sql [list 0 $result]
-}
-
-proc do_error_test {name sql error} {
- doPassiveTest $name $sql [list 1 $error]
-}
-
-proc doPassiveTest {name sql catchres} {
- if {![info exists ::DO_MALLOC_TEST]} { set ::DO_MALLOC_TEST 1 }
-
- if {$::DO_MALLOC_TEST} {
- set answers [list {1 {out of memory}} $catchres]
- set modes [list 100000 transient 1 persistent]
- } else {
- set answers [list $catchres]
- set modes [list 0 nofail]
- }
- set str [join $answers " OR "]
-
- foreach {nRepeat zName} $modes {
- for {set iFail 1} 1 {incr iFail} {
- if {$::DO_MALLOC_TEST} {sqlite3_memdebug_fail $iFail -repeat $nRepeat}
-
- set res [catchsql $sql]
- if {[lsearch $answers $res]>=0} {
- set res $str
- }
- do_test $name.$zName.$iFail [list set {} $res] $str
- set nFail [sqlite3_memdebug_fail -1 -benigncnt nBenign]
- if {$nFail==0} break
- }
- }
-}
-
-
-#-------------------------------------------------------------------------
-# Test a single write to the database. In this case a "write" is a
-# DELETE, UPDATE or INSERT statement.
-#
-# If OOM testing is performed, there are several acceptable outcomes:
-#
-# 1) The write succeeds. No error is returned.
-#
-# 2) An "out of memory" exception is thrown and:
-#
-# a) The statement has no effect, OR
-# b) The current transaction is rolled back, OR
-# c) The statement succeeds. This can only happen if the connection
-# is in auto-commit mode (after the statement is executed, so this
-# includes COMMIT statements).
-#
-# If the write operation eventually succeeds, zero is returned. If a
-# transaction is rolled back, non-zero is returned.
-#
-# Parameter $name is the name to use for the test case (or test cases).
-# The second parameter, $tbl, should be the name of the database table
-# being modified. Parameter $sql contains the SQL statement to test.
-#
-proc do_write_test {name tbl sql} {
- if {![info exists ::DO_MALLOC_TEST]} { set ::DO_MALLOC_TEST 1 }
-
- # Figure out an statement to get a checksum for table $tbl.
- db eval "SELECT * FROM $tbl" V break
- set cksumsql "SELECT md5sum([join [concat rowid $V(*)] ,]) FROM $tbl"
-
- # Calculate the initial table checksum.
- set cksum1 [db one $cksumsql]
-
-
- if {$::DO_MALLOC_TEST } {
- set answers [list {1 {out of memory}} {0 {}}]
- set modes [list 100000 transient 1 persistent]
- } else {
- set answers [list {0 {}}]
- set modes [list 0 nofail]
- }
- set str [join $answers " OR "]
-
- foreach {nRepeat zName} $modes {
- for {set iFail 1} 1 {incr iFail} {
- if {$::DO_MALLOC_TEST} {sqlite3_memdebug_fail $iFail -repeat $nRepeat}
-
- set res [catchsql $sql]
- set nFail [sqlite3_memdebug_fail -1 -benigncnt nBenign]
- if {$nFail==0} {
- do_test $name.$zName.$iFail [list set {} $res] {0 {}}
- return
- } else {
- if {[lsearch $answers $res]>=0} {
- set res $str
- }
- do_test $name.$zName.$iFail [list set {} $res] $str
- set cksum2 [db one $cksumsql]
- if {$cksum1 != $cksum2} return
- }
- }
- }
-}
proc normal_list {l} {
set ret [list]
--- /dev/null
+# 2009 December 03
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# Brute force (random data) tests for FTS3.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# If this build does not include FTS3, skip the tests in this file.
+#
+ifcapable !fts3 { finish_test ; return }
+source $testdir/fts3_common.tcl
+
+set nVocab 100
+set lVocab [list]
+
+# Generate a vocabulary of nVocab words. Each word is 3 characters long.
+#
+set lChar {a b c d e f g h i j k l m n o p q r s t u v w x y z}
+for {set i 0} {$i < $nVocab} {incr i} {
+ set word [lindex $lChar [expr int(rand()*26)]]
+ append word [lindex $lChar [expr int(rand()*26)]]
+ append word [lindex $lChar [expr int(rand()*26)]]
+ lappend lVocab $word
+}
+
+proc random_term {} {
+ lindex $::lVocab [expr {int(rand()*$::nVocab)}]
+}
+
+# Return a document consisting of $nWord arbitrarily selected terms
+# from the $::lVocab list.
+#
+proc generate_doc {nWord} {
+ set doc [list]
+ for {set i 0} {$i < $nWord} {incr i} {
+ lappend doc [random_term]
+ }
+ return $doc
+}
+
+
+
+# Primitives to update the table.
+#
+proc insert_row {rowid} {
+ set a [generate_doc [expr int((rand()*100))]]
+ set b [generate_doc [expr int((rand()*100))]]
+ set c [generate_doc [expr int((rand()*100))]]
+ execsql { INSERT INTO t1(docid, a, b, c) VALUES($rowid, $a, $b, $c) }
+ set ::t1($rowid) [list $a $b $c]
+}
+proc delete_row {rowid} {
+ execsql { DELETE FROM t1 WHERE rowid = $rowid }
+ catch {unset ::t1($rowid)}
+}
+proc update_row {rowid} {
+ set cols {a b c}
+ set iCol [expr int(rand()*3)]
+ set doc [generate_doc [expr int((rand()*100))]]
+ lset ::t1($rowid) $iCol $doc
+ execsql "UPDATE t1 SET [lindex $cols $iCol] = \$doc WHERE rowid = \$rowid"
+}
+
+# Primitives to query the in-memory table.
+#
+proc simple_term {zTerm} {
+ set ret [list]
+ foreach {key value} [array get ::t1] {
+ if {[string first $zTerm $value]>=0} { lappend ret $key }
+ }
+ lsort -integer $ret
+}
+
+foreach nodesize {50 500 1000 2000} {
+ catch { array unset ::t1 }
+
+ # Create the FTS3 table. Populate it (and the Tcl array) with 100 rows.
+ #
+ db transaction {
+ catchsql { DROP TABLE t1 }
+ execsql "CREATE VIRTUAL TABLE t1 USING fts3(a, b, c, test:$nodesize)"
+ for {set i 0} {$i < 100} {incr i} { insert_row $i }
+ }
+
+ for {set iTest 1} {$iTest <= 100} {incr iTest} {
+
+ # Delete one row, update one row and insert one row.
+ #
+ set rows [array names ::t1]
+ set nRow [llength $rows]
+ set iUpdate [lindex $rows [expr {int(rand()*$nRow)}]]
+ set iDelete $iUpdate
+ while {$iDelete == $iUpdate} {
+ set iDelete [lindex $rows [expr {int(rand()*$nRow)}]]
+ }
+ set iInsert $iUpdate
+ while {[info exists ::t1($iInsert)]} {
+ set iInsert [expr {int(rand()*1000000)}]
+ }
+ db transaction {
+ insert_row $iInsert
+ update_row $iUpdate
+ delete_row $iDelete
+ }
+
+ # Pick 10 terms from the vocabulary. Check that the results of querying
+ # the database for the set of documents containing each of these terms
+ # is the same as the result obtained by scanning the contents of the Tcl
+ # array for each term.
+ #
+ set n [expr {$iTest % ([llength $::lVocab]-10)}]
+ foreach term [lrange $::lVocab $n [expr $n+10]] {
+ do_test fts3rnd-1.$nodesize.$iTest.$term {
+ execsql { SELECT docid FROM t1 WHERE t1 MATCH $term }
+ } [simple_term $term]
+ }
+
+ # Similar to the above, except for phrase queries.
+ #
+ for {set i 0} {$i < 10} {incr i} {
+ set term [list [random_term] [random_term]]
+ set match "\"$term\""
+ do_test fts3rnd-1.$nodesize.$iTest.$match {
+ execsql { SELECT docid FROM t1 WHERE t1 MATCH $match }
+ } [simple_term $term]
+ }
+
+ # Three word phrases.
+ #
+ for {set i 0} {$i < 10} {incr i} {
+ set term [list [random_term] [random_term] [random_term]]
+ set match "\"$term\""
+ do_test fts3rnd-1.$nodesize.$iTest.$match {
+ execsql { SELECT docid FROM t1 WHERE t1 MATCH $match }
+ } [simple_term $term]
+ }
+ }
+}
+
+finish_test
+
crash6.test
crash7.test
delete3.test
+ e_fts3.test
fts3.test
+ fts3fuzz.test
fkey_malloc.test
fuzz.test
fuzz3.test