3 # The author disclaims copyright to this source code. In place of
4 # a legal notice, here is a blessing:
6 # May you do good and not evil.
7 # May you find forgiveness for yourself and forgive others.
8 # May you share freely, never taking more than you give.
10 #***********************************************************************
12 # Tests for tables that use both tokendata=1 and contentless_delete=1.
15 source [file join [file dirname [info script]] fts5_common.tcl]
16 set testprefix fts5origintext
18 # If SQLITE_ENABLE_FTS5 is defined, omit this file.
24 # Return a random integer between 0 and n-1.
26 proc random {n} { expr {abs(int(rand()*$n))} }
28 # Select an element of the list passed as the only argument at random and
31 proc select_one {list} {
33 lindex $list [random $n]
36 # Given a term that consists entirely of alphabet characters, return all
37 # permutations of the term using upper and lower case characters. e.g.
39 # "abc" -> {CBA cBA CbA cbA CBa cBa Cba cba}
41 proc casify {term {lRet {{}}}} {
42 if {$term==""} { return $lRet }
43 set t [string range $term 1 end]
44 set f1 [string toupper [string range $term 0 0]]
45 set f2 [string tolower [string range $term 0 0]]
51 return [casify $t $ret]
55 list abc def ghi jkl mno pqr stu vwx yza
58 # Return a random 3 letter term.
61 if {[info exists ::expanded_vocab]==0} {
62 foreach v [vocab] { lappend ::expanded_vocab {*}[casify $v] }
65 select_one $::expanded_vocab
68 # Return a document - between 3 and 10 terms.
71 set nTerm [expr [random 3] + 7]
73 for {set ii 0} {$ii < $nTerm} {incr ii} {
78 db func document document
80 #-------------------------------------------------------------------------
87 sqlite3_fts5_register_origintext db
91 for {set iTok 0} {$iTok < [$cmd xInstCount]} {incr iTok} {
92 set txt [$cmd xInstToken $iTok 0]
93 set txt [string map [list "\0" "."] $txt]
98 sqlite3_fts5_create_function db tokens tokens
100 proc rankfunc {cmd} {
103 sqlite3_fts5_create_function db rankfunc rankfunc
105 proc ctrl_tokens {term args} {
107 set term [string tolower $term]
110 if {[string tolower $a]==$term} {
114 lappend ret [string tolower $a].$a
121 db func ctrl_tokens ctrl_tokens
123 proc do_all_vocab_test {tn} {
124 foreach ::v [concat [vocab] nnn] {
125 set answer [execsql {
126 SELECT id, ctrl_tokens($::v, x) FROM ctrl WHERE x LIKE '%' || $::v || '%'
128 do_execsql_test $tn.$::v.1 {
129 SELECT rowid, tokens(ft) FROM ft($::v)
131 do_execsql_test $tn.$::v.2 {
132 SELECT rowid, tokens(ft) FROM ft($::v) ORDER BY rank
137 do_execsql_test 1.0 {
138 CREATE VIRTUAL TABLE ft USING fts5(
139 x, tokenize="origintext unicode61", content=, contentless_delete=1,
143 CREATE TABLE ctrl(id INTEGER PRIMARY KEY, x TEXT);
144 INSERT INTO ft(ft, rank) VALUES('pgsz', 64);
145 INSERT INTO ft(ft, rank) VALUES('rank', 'rankfunc()');
148 for {set ii 0} {$ii < $NDOC} {incr ii} {
151 INSERT INTO ft(rowid, x) VALUES($ii, $doc);
152 INSERT INTO ctrl(id, x) VALUES($ii, $doc);
157 #execsql_pp { SELECT * FROM ctrl }
158 #execsql_pp { SELECT * FROM ft }
159 #fts5_aux_test_functions db
160 #execsql_pp { SELECT rowid, tokens(ft), fts5_test_poslist(ft) FROM ft('ghi'); }
162 do_all_vocab_test 1.2
164 for {set ii 0} {$ii < $NLOOP} {incr ii} {
165 set lRowid [execsql { SELECT id FROM ctrl WHERE random() % 2 }]
167 execsql { DELETE FROM ft WHERE rowid = $r }
168 execsql { DELETE FROM ctrl WHERE rowid = $r }
171 execsql { INSERT INTO ft(rowid, x) VALUES($r, $doc) }
172 execsql { INSERT INTO ctrl(id, x) VALUES($r, $doc) }
174 do_all_vocab_test 1.3.$ii
177 #-------------------------------------------------------------------------
179 do_execsql_test 2.0 {
180 CREATE VIRTUAL TABLE ft2 USING fts5(
181 x, y, tokenize="origintext unicode61", content=, contentless_delete=1,
185 CREATE TABLE ctrl2(id INTEGER PRIMARY KEY, x TEXT, y TEXT);
186 INSERT INTO ft2(ft2, rank) VALUES('pgsz', 64);
187 INSERT INTO ft2(ft2, rank) VALUES('rank', 'rankfunc()');
190 for {set ii 0} {$ii < $NDOC} {incr ii} {
194 INSERT INTO ft2(rowid, x, y) VALUES($ii, $doc, $doc2);
195 INSERT INTO ctrl2(id, x, y) VALUES($ii, $doc, $doc2);
200 proc do_all_vocab_test2 {tn} {
201 foreach ::v [vocab] {
202 set answer [execsql {
203 SELECT id, ctrl_tokens($::v, x, y) FROM ctrl2
204 WHERE x LIKE '%' || $::v || '%' OR y LIKE '%' || $::v || '%';
206 do_execsql_test $tn.$::v.1 {
207 SELECT rowid, tokens(ft2) FROM ft2($::v)
209 do_execsql_test $tn.$::v.2 {
210 SELECT rowid, tokens(ft2) FROM ft2($::v) ORDER BY rank
215 do_all_vocab_test2 2.2
217 for {set ii 0} {$ii < $NLOOP} {incr ii} {
218 set lRowid [execsql { SELECT id FROM ctrl2 WHERE random() % 2 }]
220 execsql { DELETE FROM ft2 WHERE rowid = $r }
221 execsql { DELETE FROM ctrl2 WHERE rowid = $r }
225 execsql { INSERT INTO ft2(rowid, x, y) VALUES($r, $doc, $doc1) }
226 execsql { INSERT INTO ctrl2(id, x, y) VALUES($r, $doc, $doc2) }
228 do_all_vocab_test 2.3.$ii
231 #-------------------------------------------------------------------------
233 unset -nocomplain ::expanded_vocab
235 list abcde fghij klmno
238 proc do_all_vocab_test3 {tn} {
239 foreach ::v [concat [vocab] nnn] {
240 set answer [execsql {
241 SELECT rowid, ctrl_tokens($::v, w) FROM ctrl3 WHERE w LIKE '%' || $::v || '%'
243 do_execsql_test $tn.$::v.1 {
244 SELECT rowid, tokens(ft3) FROM ft3($::v)
246 do_execsql_test $tn.$::v.2 {
247 SELECT rowid, tokens(ft3) FROM ft3($::v) ORDER BY rank
252 do_execsql_test 3.0 {
253 CREATE VIRTUAL TABLE ft3 USING fts5(
254 w, tokenize="origintext unicode61", content=, contentless_delete=1,
257 INSERT INTO ft3(ft3, rank) VALUES('rank', 'rankfunc()');
258 CREATE TABLE ctrl3(w);
261 do_execsql_test 3.1 {
263 SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<2
265 INSERT INTO ctrl3 SELECT document() FROM s;
266 INSERT INTO ft3(rowid, w) SELECT rowid, w FROM ctrl3;
269 do_all_vocab_test3 3.2