123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- # 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
|