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 #*************************************************************************
11 # This file implements regression tests for SQLite library. The
12 # focus of this script is testing the FTS5 module.
15 source [file join [file dirname [info script]] fts5_common.tcl]
16 source $testdir/malloc_common.tcl
17 set testprefix fts5fault1
19 # If SQLITE_ENABLE_FTS3 is defined, omit this file.
27 # 1: CREATE VIRTUAL TABLE
30 # 4: MATCH expressions
34 faultsim_save_and_close
35 do_faultsim_test 1 -faults ioerr-t* -prep {
36 faultsim_restore_and_reopen
38 execsql { CREATE VIRTUAL TABLE t1 USING fts5(a, b, prefix='1, 2, 3') }
40 faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}}
45 CREATE VIRTUAL TABLE t1 USING fts5(a, b, prefix='1, 2, 3');
47 faultsim_save_and_close
48 do_faultsim_test 2 -prep {
49 faultsim_restore_and_reopen
52 INSERT INTO t1 VALUES('a b c', 'a bc def ghij klmno');
55 faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}}
60 CREATE VIRTUAL TABLE t1 USING fts5(a, b, prefix='1, 2, 3');
61 INSERT INTO t1 VALUES('a b c', 'a bc def ghij klmno');
63 faultsim_save_and_close
64 do_faultsim_test 3 -prep {
65 faultsim_restore_and_reopen
67 execsql { DELETE FROM t1 }
69 faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}}
74 CREATE VIRTUAL TABLE t2 USING fts5(a, b);
75 INSERT INTO t2 VALUES('m f a jj th q gi ar', 'hj n h h sg j i m');
76 INSERT INTO t2 VALUES('nr s t g od j kf h', 'sb h aq rg op rb n nl');
77 INSERT INTO t2 VALUES('do h h pb p p q fr', 'c rj qs or cr a l i');
78 INSERT INTO t2 VALUES('lk gp t i lq mq qm p', 'h mr g f op ld aj h');
79 INSERT INTO t2 VALUES('ct d sq kc qi k f j', 'sn gh c of g s qt q');
80 INSERT INTO t2 VALUES('d ea d d om mp s ab', 'dm hg l df cm ft pa c');
81 INSERT INTO t2 VALUES('tc dk c jn n t sr ge', 'a a kn bc n i af h');
82 INSERT INTO t2 VALUES('ie ii d i b sa qo rf', 'a h m aq i b m fn');
83 INSERT INTO t2 VALUES('gs r fo a er m h li', 'tm c p gl eb ml q r');
84 INSERT INTO t2 VALUES('k fe fd rd a gi ho kk', 'ng m c r d ml rm r');
86 faultsim_save_and_close
88 foreach {tn expr res} {
91 3 { f* } {1 3 4 5 6 8 9 10}
92 4 { m OR f } {1 4 5 8 9 10}
95 7 { NEAR(r a, 5) } {9}
96 8 { m* f* } {1 4 6 8 9 10}
98 10 { c NOT p } {5 6 7 10}
100 do_faultsim_test 4.$tn -prep {
101 faultsim_restore_and_reopen
103 execsql { SELECT rowid FROM t2 WHERE t2 MATCH '$expr' }
105 faultsim_test_result {[list 0 $res]} {1 {vtable constructor failed: t2}}
110 #-------------------------------------------------------------------------
111 # The following tests use a larger database populated with random data.
113 # The database page size is set to 512 bytes and the FTS5 page size left
114 # at the default 1000 bytes. This means that reading a node may require
115 # pulling an overflow page from disk, which is an extra opportunity for
119 do_execsql_test 5.0.1 {
120 PRAGMA main.page_size = 512;
121 CREATE VIRTUAL TABLE x1 USING fts5(a, b);
122 PRAGMA main.page_size;
126 set map [list 0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j]
128 for {set i 0} {$i < $n} {incr i} {
129 lappend doc [string map $map [format %.3d [expr int(rand()*1000)]]]
133 db func rnddoc rnddoc
135 do_execsql_test 5.0.2 {
137 SELECT rnddoc(6), rnddoc(6) UNION ALL
138 SELECT rnddoc(6), rnddoc(6) FROM r
140 INSERT INTO x1 SELECT * FROM r LIMIT 10000;
144 SELECT count(*) FROM x1 WHERE x1.a LIKE '%abc%' OR x1.b LIKE '%abc%'}
147 do_faultsim_test 5.1 -faults oom* -body {
148 execsql { SELECT count(*) FROM x1 WHERE x1 MATCH 'abc' }
150 faultsim_test_result [list 0 $::res]
152 do_faultsim_test 5.2 -faults oom* -body {
153 execsql { SELECT count(*) FROM x1 WHERE x1 MATCH 'abcd' }
155 faultsim_test_result [list 0 0]
158 proc test_astar {a b} {
159 return [expr { [regexp {a[^ ][^ ]} $a] || [regexp {a[^ ][^ ]} $b] }]
161 db func test_astar test_astar
163 set res [db one { SELECT count(*) FROM x1 WHERE test_astar(a, b) } ]
164 do_faultsim_test 5.3 -faults oom* -body {
165 execsql { SELECT count(*) FROM x1 WHERE x1 MATCH 'a*' }
167 faultsim_test_result [list 0 $::res]
170 do_faultsim_test 5.4 -faults oom* -prep {
174 execsql { INSERT INTO x1 VALUES('a b c d', 'e f g h') }
176 faultsim_test_result [list 0 {}]
179 do_faultsim_test 5.5.1 -faults oom* -body {
181 SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid=1
184 faultsim_test_result [list 0 1]
186 do_faultsim_test 5.5.2 -faults oom* -body {
188 SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid=10
191 faultsim_test_result [list 0 1]
193 do_faultsim_test 5.5.3 -faults oom* -body {
195 SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid = (
196 SELECT min(rowid) FROM x1_data WHERE rowid>20
200 faultsim_test_result [list 0 1]
202 do_faultsim_test 5.5.4 -faults oom* -body {
204 SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid = (
205 SELECT max(rowid) FROM x1_data
209 faultsim_test_result [list 0 1]
212 #-------------------------------------------------------------------------
215 do_execsql_test 6.0 {
216 CREATE VIRTUAL TABLE x1 USING fts5(x);
217 INSERT INTO x1(x1, rank) VALUES('automerge', 0);
219 INSERT INTO x1 VALUES('a b c'); -- 1
220 INSERT INTO x1 VALUES('a b c'); -- 2
221 INSERT INTO x1 VALUES('a b c'); -- 3
222 INSERT INTO x1 VALUES('a b c'); -- 4
223 INSERT INTO x1 VALUES('a b c'); -- 5
224 INSERT INTO x1 VALUES('a b c'); -- 6
225 INSERT INTO x1 VALUES('a b c'); -- 7
226 INSERT INTO x1 VALUES('a b c'); -- 8
227 INSERT INTO x1 VALUES('a b c'); -- 9
228 INSERT INTO x1 VALUES('a b c'); -- 10
229 INSERT INTO x1 VALUES('a b c'); -- 11
230 INSERT INTO x1 VALUES('a b c'); -- 12
231 INSERT INTO x1 VALUES('a b c'); -- 13
232 INSERT INTO x1 VALUES('a b c'); -- 14
233 INSERT INTO x1 VALUES('a b c'); -- 15
235 SELECT count(*) FROM x1_data;
238 faultsim_save_and_close
240 do_faultsim_test 6.1 -faults oom* -prep {
241 faultsim_restore_and_reopen
243 execsql { INSERT INTO x1 VALUES('d e f') }
245 faultsim_test_result [list 0 {}]
247 set nCnt [db one {SELECT count(*) FROM x1_data}]
248 if {$nCnt!=3} { error "expected 3 entries but there are $nCnt" }
252 do_faultsim_test 6.2 -faults oom* -prep {
253 faultsim_restore_and_reopen
255 execsql { INSERT INTO x1(x1, rank) VALUES('pgsz', 32) }
257 faultsim_test_result [list 0 {}]
260 do_faultsim_test 6.3 -faults oom-* -prep {
261 faultsim_restore_and_reopen
263 execsql { INSERT INTO x1(x1) VALUES('integrity-check') }
265 faultsim_test_result [list 0 {}]
268 do_faultsim_test 6.4 -faults oom-* -prep {
269 faultsim_restore_and_reopen
271 execsql { INSERT INTO x1(x1) VALUES('optimize') }
273 faultsim_test_result [list 0 {}]
276 #-------------------------------------------------------------------------
278 do_faultsim_test 7.0 -faults oom* -prep {
283 faultsim_test_result [list 0 {}] {1 {}} {1 {initialization of fts5 failed: }}
286 #-------------------------------------------------------------------------
287 # A prefix query against a large document set.
290 set map [list 0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j]
292 for {set i 0} {$i < $n} {incr i} {
293 lappend doc "x[string map $map [format %.3d [expr int(rand()*1000)]]]"
299 db func rnddoc rnddoc
302 execsql { CREATE VIRTUAL TABLE x1 USING fts5(a) }
304 for {set i 1} {$i<100} {incr i 1} {
305 execsql { INSERT INTO x1 VALUES( rnddoc(50) ) }
310 do_faultsim_test 8.1 -faults oom* -prep {
313 SELECT rowid FROM x1 WHERE x1 MATCH 'x*'
316 faultsim_test_result [list 0 $::res]
319 #-------------------------------------------------------------------------
324 db func rnddoc fts5_rnddoc
326 CREATE VIRTUAL TABLE s2 USING fts5(x);
327 INSERT INTO s2(s2, rank) VALUES('pgsz', 32);
328 INSERT INTO s2(s2, rank) VALUES('automerge', 0);
331 for {set i 1} {$i <= 16} {incr i} {
332 execsql { INSERT INTO s2 VALUES(rnddoc(5)) }
336 set insert_doc [db one {SELECT rnddoc(160)}]
337 faultsim_save_and_close
339 do_faultsim_test 9.1 -faults oom-* -prep {
340 faultsim_restore_and_reopen
342 execsql { INSERT INTO s2 VALUES($::insert_doc) }
344 faultsim_test_result {0 {}}
346 set ls [fts5_level_segs s2]
347 if {$ls != "2 0"} { error "fts5_level_segs says {$ls}" }