Fix an incorrect assert() in fts3.c. Add further fts3 tests.

FossilOrigin-Name: 75863c2d55e0801add5b8dcf88d575c5c870af04
This commit is contained in:
dan 2009-12-03 17:36:22 +00:00
parent e585b8f05c
commit e2e5145441
8 changed files with 249 additions and 196 deletions

View File

@ -473,11 +473,6 @@ static void fts3GetDeltaVarint2(char **pp, char *pEnd, sqlite3_int64 *pVal){
}
}
static Fts3Table *cursor_vtab(Fts3Cursor *c){
return (Fts3Table *) c->base.pVtab;
}
/*
** The xDisconnect() virtual table method.
*/
@ -650,6 +645,14 @@ int fts3InitVtab(
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 */
@ -696,6 +699,7 @@ int fts3InitVtab(
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);
@ -739,6 +743,11 @@ int fts3InitVtab(
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:
@ -1010,12 +1019,16 @@ static int fts3SelectLeaf(
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;
}
@ -1550,6 +1563,7 @@ static int fts3TermSelect(
sqlite3_int64 i2 = sqlite3_column_int64(pStmt, 2);
rc = sqlite3Fts3SegReaderNew(p, iAge, i1, i2, 0, 0, 0, &pNew);
}
sqlite3Fts3ReadBlock(p, 0, 0, 0);
}
iAge++;
@ -1699,6 +1713,9 @@ static int evalFts3Expr(
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;
@ -1749,8 +1766,7 @@ static int evalFts3Expr(
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
@ -1865,38 +1881,6 @@ static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){
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
@ -1913,6 +1897,43 @@ static int fts3RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
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

View File

@ -115,6 +115,8 @@ struct Fts3Table {
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.

View File

@ -24,9 +24,6 @@
#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;
@ -279,16 +276,18 @@ int sqlite3Fts3ReadBlock(
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;
}
@ -1193,13 +1192,13 @@ static int fts3NodeAddTerm(
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.
*/
@ -1248,7 +1247,7 @@ static int fts3NodeAddTerm(
** 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;
}
@ -1401,9 +1400,9 @@ static int fts3SegWriterAdd(
*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);
@ -1427,7 +1426,7 @@ static int fts3SegWriterAdd(
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. */

View File

@ -1,5 +1,5 @@
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
@ -56,9 +56,9 @@ F ext/fts2/mkfts2amal.tcl 974d5d438cb3f7c4a652639262f82418c1e4cff0
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
@ -68,7 +68,7 @@ F ext/fts3/fts3_snippet.c 6c2eb6d872d66b2a9aa5663f2662e993f18a6496
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
@ -400,8 +400,9 @@ F test/fts3d.test 95fb3c862cbc4297c93fceb9a635543744e9ef52
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
@ -522,7 +523,7 @@ F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47
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
@ -775,7 +776,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
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

View File

@ -1 +1 @@
37495b55ffbdc2db4482367ac7d8e32d4d71d58e
75863c2d55e0801add5b8dcf88d575c5c870af04

View File

@ -36,126 +36,6 @@ set DO_MALLOC_TEST 1
#
#
#-------------------------------------------------------------------------
# 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]

148
test/fts3rnd.test Normal file
View File

@ -0,0 +1,148 @@
# 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

View File

@ -57,7 +57,9 @@ set EXCLUDE {
crash6.test
crash7.test
delete3.test
e_fts3.test
fts3.test
fts3fuzz.test
fkey_malloc.test
fuzz.test
fuzz3.test