diff options
Diffstat (limited to 'test/fts3an.test')
-rw-r--r-- | test/fts3an.test | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/test/fts3an.test b/test/fts3an.test new file mode 100644 index 0000000..5211027 --- /dev/null +++ b/test/fts3an.test @@ -0,0 +1,218 @@ +# 2007 April 26 +# +# The author disclaims copyright to this source code. +# +#************************************************************************* +# This file implements tests for prefix-searching in the fts3 +# component of the SQLite library. +# +# $Id: fts3an.test,v 1.2 2007/12/13 21:54:11 drh Exp $ +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +# If SQLITE_ENABLE_FTS3 is defined, omit this file. +ifcapable !fts3 { + finish_test + return +} + +# A large string to prime the pump with. +set text { + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas + iaculis mollis ipsum. Praesent rhoncus placerat justo. Duis non quam + sed turpis posuere placerat. Curabitur et lorem in lorem porttitor + aliquet. Pellentesque bibendum tincidunt diam. Vestibulum blandit + ante nec elit. In sapien diam, facilisis eget, dictum sed, viverra + at, felis. Vestibulum magna. Sed magna dolor, vestibulum rhoncus, + ornare vel, vulputate sit amet, felis. Integer malesuada, tellus at + luctus gravida, diam nunc porta nibh, nec imperdiet massa metus eu + lectus. Aliquam nisi. Nunc fringilla nulla at lectus. Suspendisse + potenti. Cum sociis natoque penatibus et magnis dis parturient + montes, nascetur ridiculus mus. Pellentesque odio nulla, feugiat eu, + suscipit nec, consequat quis, risus. +} + +db eval { + CREATE VIRTUAL TABLE t1 USING fts3(c); + + INSERT INTO t1(rowid, c) VALUES(1, $text); + INSERT INTO t1(rowid, c) VALUES(2, 'Another lovely row'); +} + +# Exact match +do_test fts3an-1.1 { + execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lorem'" +} {1} + +# And a prefix +do_test fts3an-1.2 { + execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lore*'" +} {1} + +# Prefix includes exact match +do_test fts3an-1.3 { + execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lorem*'" +} {1} + +# Make certain everything isn't considered a prefix! +do_test fts3an-1.4 { + execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lore'" +} {} + +# Prefix across multiple rows. +do_test fts3an-1.5 { + execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lo*'" +} {1 2} + +# Likewise, with multiple hits in one document. +do_test fts3an-1.6 { + execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'l*'" +} {1 2} + +# Prefix which should only hit one document. +do_test fts3an-1.7 { + execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lov*'" +} {2} + +# * not at end is dropped. +do_test fts3an-1.8 { + execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lo *'" +} {} + +# Stand-alone * is dropped. +do_test fts3an-1.9 { + execsql "SELECT rowid FROM t1 WHERE t1 MATCH '*'" +} {} + +# Phrase-query prefix. +do_test fts3an-1.10 { + execsql "SELECT rowid FROM t1 WHERE t1 MATCH '\"lovely r*\"'" +} {2} +do_test fts3an-1.11 { + execsql "SELECT rowid FROM t1 WHERE t1 MATCH '\"lovely r\"'" +} {} + +# Phrase query with multiple prefix matches. +do_test fts3an-1.12 { + execsql "SELECT rowid FROM t1 WHERE t1 MATCH '\"a* l*\"'" +} {1 2} + +# Phrase query with multiple prefix matches. +do_test fts3an-1.13 { + execsql "SELECT rowid FROM t1 WHERE t1 MATCH '\"a* l* row\"'" +} {2} + + + + +# Test across updates (and, by implication, deletes). + +# Version of text without "lorem". +regsub -all {[Ll]orem} $text '' ntext + +db eval { + CREATE VIRTUAL TABLE t2 USING fts3(c); + + INSERT INTO t2(rowid, c) VALUES(1, $text); + INSERT INTO t2(rowid, c) VALUES(2, 'Another lovely row'); + UPDATE t2 SET c = $ntext WHERE rowid = 1; +} + +# Can't see lorem as an exact match. +do_test fts3an-2.1 { + execsql "SELECT rowid FROM t2 WHERE t2 MATCH 'lorem'" +} {} + +# Can't see a prefix of lorem, either. +do_test fts3an-2.2 { + execsql "SELECT rowid FROM t2 WHERE t2 MATCH 'lore*'" +} {} + +# Can see lovely in the other document. +do_test fts3an-2.3 { + execsql "SELECT rowid FROM t2 WHERE t2 MATCH 'lo*'" +} {2} + +# Can still see other hits. +do_test fts3an-2.4 { + execsql "SELECT rowid FROM t2 WHERE t2 MATCH 'l*'" +} {1 2} + +# Prefix which should only hit one document. +do_test fts3an-2.5 { + execsql "SELECT rowid FROM t2 WHERE t2 MATCH 'lov*'" +} {2} + + + +# Test with a segment which will have multiple levels in the tree. + +# Build a big document with lots of unique terms. +set bigtext $text +foreach c {a b c d e} { + regsub -all {[A-Za-z]+} $bigtext "&$c" t + append bigtext $t +} + +# Populate a table with many copies of the big document, so that we +# can test the number of hits found. Populate $ret with the expected +# hit counts for each row. offsets() returns 4 elements for every +# hit. We'll have 6 hits for row 1, 1 for row 2, and 6*(2^5)==192 for +# $bigtext. +set ret {6 1} +db eval { + BEGIN; + CREATE VIRTUAL TABLE t3 USING fts3(c); + + INSERT INTO t3(rowid, c) VALUES(1, $text); + INSERT INTO t3(rowid, c) VALUES(2, 'Another lovely row'); +} +for {set i 0} {$i<68} {incr i} { + db eval {INSERT INTO t3(rowid, c) VALUES(3+$i, $bigtext)} + lappend ret 192 +} +db eval {COMMIT;} + +# Test that we get the expected number of hits. +do_test fts3an-3.1 { + set t {} + db eval {SELECT offsets(t3) as o FROM t3 WHERE t3 MATCH 'l*'} { + set l [llength $o] + lappend t [expr {$l/4}] + } + set t +} $ret + +# Test a boundary condition: More than 2^16 terms that match a searched for +# prefix in a single segment. +# +puts "This next test can take a little while (~ 30 seconds)..." +do_test fts3an-4.1 { + execsql { CREATE VIRTUAL TABLE ft USING fts3(x) } + execsql BEGIN + execsql { INSERT INTO ft VALUES(NULL) } + execsql { INSERT INTO ft SELECT * FROM ft } ;# 2 + execsql { INSERT INTO ft SELECT * FROM ft } ;# 4 + execsql { INSERT INTO ft SELECT * FROM ft } ;# 8 + execsql { INSERT INTO ft SELECT * FROM ft } ;# 16 + execsql { INSERT INTO ft SELECT * FROM ft } ;# 32 + execsql { INSERT INTO ft SELECT * FROM ft } ;# 64 + execsql { INSERT INTO ft SELECT * FROM ft } ;# 128 + execsql { INSERT INTO ft SELECT * FROM ft } ;# 256 + execsql { INSERT INTO ft SELECT * FROM ft } ;# 512 + execsql { INSERT INTO ft SELECT * FROM ft } ;# 1024 + execsql { INSERT INTO ft SELECT * FROM ft } ;# 2048 + execsql { INSERT INTO ft SELECT * FROM ft } ;# 4096 + execsql { INSERT INTO ft SELECT * FROM ft } ;# 8192 + execsql { INSERT INTO ft SELECT * FROM ft } ;# 16384 + execsql { INSERT INTO ft SELECT * FROM ft } ;# 32768 + execsql { INSERT INTO ft SELECT * FROM ft } ;# 65536 + execsql { INSERT INTO ft SELECT * FROM ft } ;# 131072 + execsql COMMIT + execsql { UPDATE ft SET x = 'abc' || rowid } + execsql { SELECT count(*) FROM ft WHERE x MATCH 'abc*' } +} {131072} + +finish_test |