OLD | NEW |
| (Empty) |
1 # 2014 June 17 | |
2 # | |
3 # The author disclaims copyright to this source code. In place of | |
4 # a legal notice, here is a blessing: | |
5 # | |
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. | |
9 # | |
10 #************************************************************************* | |
11 # | |
12 # This file is focused on OOM errors. | |
13 # | |
14 | |
15 source [file join [file dirname [info script]] fts5_common.tcl] | |
16 source $testdir/malloc_common.tcl | |
17 set testprefix fts5fault4 | |
18 | |
19 # If SQLITE_ENABLE_FTS3 is defined, omit this file. | |
20 ifcapable !fts5 { | |
21 finish_test | |
22 return | |
23 } | |
24 | |
25 #------------------------------------------------------------------------- | |
26 # An OOM while dropping an fts5 table. | |
27 # | |
28 db func rnddoc fts5_rnddoc | |
29 do_test 1.0 { | |
30 execsql { CREATE VIRTUAL TABLE xx USING fts5(x) } | |
31 } {} | |
32 faultsim_save_and_close | |
33 | |
34 do_faultsim_test 1 -faults oom-* -prep { | |
35 faultsim_restore_and_reopen | |
36 execsql { SELECT * FROM xx } | |
37 } -body { | |
38 execsql { DROP TABLE xx } | |
39 } -test { | |
40 faultsim_test_result [list 0 {}] | |
41 } | |
42 | |
43 #------------------------------------------------------------------------- | |
44 # An OOM within an "ORDER BY rank" query. | |
45 # | |
46 db func rnddoc fts5_rnddoc | |
47 do_execsql_test 2.0 { | |
48 CREATE VIRTUAL TABLE xx USING fts5(x); | |
49 INSERT INTO xx VALUES ('abc ' || rnddoc(10)); | |
50 INSERT INTO xx VALUES ('abc abc' || rnddoc(9)); | |
51 INSERT INTO xx VALUES ('abc abc abc' || rnddoc(8)); | |
52 } {} | |
53 faultsim_save_and_close | |
54 | |
55 do_faultsim_test 2 -faults oom-* -prep { | |
56 faultsim_restore_and_reopen | |
57 execsql { SELECT * FROM xx } | |
58 } -body { | |
59 execsql { SELECT rowid FROM xx WHERE xx MATCH 'abc' ORDER BY rank } | |
60 } -test { | |
61 faultsim_test_result [list 0 {3 2 1}] | |
62 } | |
63 | |
64 #------------------------------------------------------------------------- | |
65 # An OOM while "reseeking" an FTS cursor. | |
66 # | |
67 do_execsql_test 3.0 { | |
68 CREATE VIRTUAL TABLE jj USING fts5(j); | |
69 INSERT INTO jj(rowid, j) VALUES(101, 'm t w t f s s'); | |
70 INSERT INTO jj(rowid, j) VALUES(202, 't w t f s'); | |
71 INSERT INTO jj(rowid, j) VALUES(303, 'w t f'); | |
72 INSERT INTO jj(rowid, j) VALUES(404, 't'); | |
73 } | |
74 faultsim_save_and_close | |
75 | |
76 do_faultsim_test 3 -faults oom-* -prep { | |
77 faultsim_restore_and_reopen | |
78 execsql { SELECT * FROM jj } | |
79 } -body { | |
80 set res [list] | |
81 db eval { SELECT rowid FROM jj WHERE jj MATCH 't' } { | |
82 lappend res $rowid | |
83 if {$rowid==303} { | |
84 execsql { DELETE FROM jj WHERE rowid=404 } | |
85 } | |
86 } | |
87 set res | |
88 } -test { | |
89 faultsim_test_result [list 0 {101 202 303}] | |
90 } | |
91 | |
92 #------------------------------------------------------------------------- | |
93 # An OOM within a special "*reads" query. | |
94 # | |
95 reset_db | |
96 db func rnddoc fts5_rnddoc | |
97 do_execsql_test 4.0 { | |
98 CREATE VIRTUAL TABLE x1 USING fts5(x); | |
99 INSERT INTO x1(x1, rank) VALUES('pgsz', 32); | |
100 | |
101 WITH ii(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<10 ) | |
102 INSERT INTO x1 SELECT rnddoc(5) FROM ii; | |
103 } | |
104 | |
105 set ::res [db eval {SELECT rowid, x1 FROM x1 WHERE x1 MATCH '*reads'}] | |
106 | |
107 do_faultsim_test 4 -faults oom-* -body { | |
108 db eval {SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads'} | |
109 } -test { | |
110 faultsim_test_result {0 {0 {} 4}} | |
111 } | |
112 | |
113 #------------------------------------------------------------------------- | |
114 # An OOM within a query that uses a custom rank function. | |
115 # | |
116 reset_db | |
117 do_execsql_test 5.0 { | |
118 PRAGMA encoding='utf16'; | |
119 CREATE VIRTUAL TABLE x2 USING fts5(x); | |
120 INSERT INTO x2(rowid, x) VALUES(10, 'a b c'); -- 3 | |
121 INSERT INTO x2(rowid, x) VALUES(20, 'a b c'); -- 6 | |
122 INSERT INTO x2(rowid, x) VALUES(30, 'a b c'); -- 2 | |
123 INSERT INTO x2(rowid, x) VALUES(40, 'a b c'); -- 5 | |
124 INSERT INTO x2(rowid, x) VALUES(50, 'a b c'); -- 1 | |
125 } | |
126 | |
127 proc rowidmod {cmd mod} { | |
128 set row [$cmd xRowid] | |
129 expr {$row % $mod} | |
130 } | |
131 sqlite3_fts5_create_function db rowidmod rowidmod | |
132 | |
133 do_faultsim_test 5.1 -faults oom-* -body { | |
134 db eval { | |
135 SELECT rowid || '-' || rank FROM x2 WHERE x2 MATCH 'b' AND | |
136 rank MATCH "rowidmod('7')" ORDER BY rank | |
137 } | |
138 } -test { | |
139 faultsim_test_result {0 {50-1 30-2 10-3 40-5 20-6}} | |
140 } | |
141 | |
142 proc rowidprefix {cmd prefix} { | |
143 set row [$cmd xRowid] | |
144 set {} "${row}-${prefix}" | |
145 } | |
146 sqlite3_fts5_create_function db rowidprefix rowidprefix | |
147 | |
148 set str [string repeat abcdefghijklmnopqrstuvwxyz 10] | |
149 do_faultsim_test 5.2 -faults oom-* -body { | |
150 db eval " | |
151 SELECT rank, x FROM x2 WHERE x2 MATCH 'b' AND | |
152 rank MATCH 'rowidprefix(''$::str'')' | |
153 LIMIT 1 | |
154 " | |
155 } -test { | |
156 faultsim_test_result "0 {10-$::str {a b c}}" | |
157 } | |
158 | |
159 | |
160 #------------------------------------------------------------------------- | |
161 # OOM errors within auxiliary functions. | |
162 # | |
163 reset_db | |
164 do_execsql_test 6.0 { | |
165 CREATE VIRTUAL TABLE x3 USING fts5(xxx); | |
166 INSERT INTO x3 VALUES('a b c d c b a'); | |
167 INSERT INTO x3 VALUES('a a a a a a a'); | |
168 INSERT INTO x3 VALUES('a a a a a a a'); | |
169 } | |
170 | |
171 do_faultsim_test 6.1 -faults oom-t* -body { | |
172 db eval { SELECT highlight(x3, 0, '*', '*') FROM x3 WHERE x3 MATCH 'c' } | |
173 } -test { | |
174 faultsim_test_result {0 {{a b *c* d *c* b a}}} | |
175 } | |
176 | |
177 proc firstinst {cmd} { | |
178 foreach {p c o} [$cmd xInst 0] {} | |
179 expr $c*100 + $o | |
180 } | |
181 sqlite3_fts5_create_function db firstinst firstinst | |
182 | |
183 do_faultsim_test 6.2 -faults oom-t* -body { | |
184 db eval { SELECT firstinst(x3) FROM x3 WHERE x3 MATCH 'c' } | |
185 } -test { | |
186 faultsim_test_result {0 2} {1 SQLITE_NOMEM} | |
187 } | |
188 | |
189 proc previc {cmd} { | |
190 set res [$cmd xGetAuxdataInt 0] | |
191 $cmd xSetAuxdataInt [$cmd xInstCount] | |
192 return $res | |
193 } | |
194 sqlite3_fts5_create_function db previc previc | |
195 | |
196 do_faultsim_test 6.2 -faults oom-t* -body { | |
197 db eval { SELECT previc(x3) FROM x3 WHERE x3 MATCH 'a' } | |
198 } -test { | |
199 faultsim_test_result {0 {0 2 7}} {1 SQLITE_NOMEM} | |
200 } | |
201 | |
202 #------------------------------------------------------------------------- | |
203 # OOM error when querying for a phrase with many tokens. | |
204 # | |
205 reset_db | |
206 do_execsql_test 7.0 { | |
207 CREATE VIRTUAL TABLE tt USING fts5(x, y); | |
208 INSERT INTO tt VALUES('f b g b c b', 'f a d c c b'); -- 1 | |
209 INSERT INTO tt VALUES('d a e f e d', 'f b b d e e'); -- 2 | |
210 INSERT INTO tt VALUES('f b g a d c', 'e f c f a d'); -- 3 | |
211 INSERT INTO tt VALUES('f f c d g f', 'f a e b g b'); -- 4 | |
212 INSERT INTO tt VALUES('a g b d a g', 'e g a e a c'); -- 5 | |
213 INSERT INTO tt VALUES('c d b d e f', 'f g e g e e'); -- 6 | |
214 INSERT INTO tt VALUES('e g f f b c', 'f c e f g f'); -- 7 | |
215 INSERT INTO tt VALUES('e g c f c e', 'f e e a f g'); -- 8 | |
216 INSERT INTO tt VALUES('e a e b e e', 'd c c f f f'); -- 9 | |
217 INSERT INTO tt VALUES('f a g g c c', 'e g d g c e'); -- 10 | |
218 INSERT INTO tt VALUES('c d b a e f', 'f g e h e e'); -- 11 | |
219 | |
220 CREATE VIRTUAL TABLE tt2 USING fts5(o); | |
221 INSERT INTO tt2(rowid, o) SELECT rowid, x||' '||y FROM tt; | |
222 INSERT INTO tt2(rowid, o) VALUES(12, 'a b c d e f g h i j k l'); | |
223 } | |
224 | |
225 do_faultsim_test 7.2 -faults oom-* -body { | |
226 db eval { SELECT rowid FROM tt WHERE tt MATCH 'f+g+e+g+e+e' } | |
227 } -test { | |
228 faultsim_test_result {0 6} {1 SQLITE_NOMEM} | |
229 } | |
230 | |
231 do_faultsim_test 7.3 -faults oom-* -body { | |
232 db eval { SELECT rowid FROM tt WHERE tt MATCH 'NEAR(a b c d e f)' } | |
233 } -test { | |
234 faultsim_test_result {0 11} {1 SQLITE_NOMEM} | |
235 } | |
236 | |
237 do_faultsim_test 7.4 -faults oom-t* -body { | |
238 db eval { SELECT rowid FROM tt2 WHERE tt2 MATCH '"g c f c e f e e a f"' } | |
239 } -test { | |
240 faultsim_test_result {0 8} {1 SQLITE_NOMEM} | |
241 } | |
242 | |
243 do_faultsim_test 7.5 -faults oom-* -body { | |
244 db eval {SELECT rowid FROM tt2 WHERE tt2 MATCH 'NEAR(a b c d e f g h i j k)'} | |
245 } -test { | |
246 faultsim_test_result {0 12} {1 SQLITE_NOMEM} | |
247 } | |
248 | |
249 do_faultsim_test 7.6 -faults oom-* -body { | |
250 db eval {SELECT rowid FROM tt WHERE tt MATCH 'y: "c c"'} | |
251 } -test { | |
252 faultsim_test_result {0 {1 9}} {1 SQLITE_NOMEM} | |
253 } | |
254 | |
255 #------------------------------------------------------------------------- | |
256 # | |
257 reset_db | |
258 do_execsql_test 8.0 { | |
259 CREATE VIRTUAL TABLE tt USING fts5(x); | |
260 INSERT INTO tt(tt, rank) VALUES('pgsz', 32); | |
261 BEGIN; | |
262 INSERT INTO tt(rowid, x) VALUES(1, 'a b c d x x'); | |
263 WITH ii(i) AS (SELECT 2 UNION ALL SELECT i+1 FROM ii WHERE i<99) | |
264 INSERT INTO tt(rowid, x) SELECT i, 'a b c x x d' FROM ii; | |
265 INSERT INTO tt(rowid, x) VALUES(100, 'a b c d x x'); | |
266 COMMIT; | |
267 } | |
268 | |
269 do_faultsim_test 8.1 -faults oom-t* -body { | |
270 db eval { SELECT rowid FROM tt WHERE tt MATCH 'NEAR(a b c d, 2)' } | |
271 } -test { | |
272 faultsim_test_result {0 {1 100}} {1 SQLITE_NOMEM} | |
273 } | |
274 | |
275 do_faultsim_test 8.2 -faults oom-t* -body { | |
276 db eval { SELECT count(*) FROM tt WHERE tt MATCH 'a OR d' } | |
277 } -test { | |
278 faultsim_test_result {0 100} {1 SQLITE_NOMEM} | |
279 } | |
280 | |
281 | |
282 #------------------------------------------------------------------------- | |
283 # Fault in NOT query. | |
284 # | |
285 reset_db | |
286 do_execsql_test 9.0 { | |
287 CREATE VIRTUAL TABLE tt USING fts5(x); | |
288 INSERT INTO tt(tt, rank) VALUES('pgsz', 32); | |
289 BEGIN; | |
290 WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<200) | |
291 INSERT INTO tt(rowid, x) | |
292 SELECT i, CASE WHEN (i%50)==0 THEN 'a a a a a a' ELSE 'a x a x a x' END | |
293 FROM ii; | |
294 COMMIT; | |
295 } | |
296 | |
297 do_faultsim_test 9.1 -faults oom-* -body { | |
298 db eval { SELECT rowid FROM tt WHERE tt MATCH 'a NOT x' } | |
299 } -test { | |
300 faultsim_test_result {0 {50 100 150 200}} {1 SQLITE_NOMEM} | |
301 } | |
302 | |
303 #------------------------------------------------------------------------- | |
304 # OOM in fts5_expr() SQL function. | |
305 # | |
306 do_faultsim_test 10.1 -faults oom-t* -body { | |
307 db one { SELECT fts5_expr('a AND b NEAR(a b)') } | |
308 } -test { | |
309 faultsim_test_result {0 {"a" AND "b" AND NEAR("a" "b", 10)}} | |
310 } | |
311 | |
312 do_faultsim_test 10.2 -faults oom-t* -body { | |
313 db one { SELECT fts5_expr_tcl('x:"a b c" AND b NEAR(a b)', 'ns', 'x') } | |
314 } -test { | |
315 set res {AND [ns -col 0 -- {a b c}] [ns -- {b}] [ns -near 10 -- {a} {b}]} | |
316 faultsim_test_result [list 0 $res] | |
317 } | |
318 | |
319 do_faultsim_test 10.3 -faults oom-t* -body { | |
320 db one { SELECT fts5_expr('x:a', 'x') } | |
321 } -test { | |
322 faultsim_test_result {0 {x : "a"}} | |
323 } | |
324 | |
325 #------------------------------------------------------------------------- | |
326 # OOM while configuring 'rank' option. | |
327 # | |
328 reset_db | |
329 do_execsql_test 11.0 { | |
330 CREATE VIRTUAL TABLE ft USING fts5(x); | |
331 } | |
332 do_faultsim_test 11.1 -faults oom-t* -body { | |
333 db eval { INSERT INTO ft(ft, rank) VALUES('rank', 'bm25(10.0, 5.0)') } | |
334 } -test { | |
335 faultsim_test_result {0 {}} {1 {disk I/O error}} | |
336 } | |
337 | |
338 #------------------------------------------------------------------------- | |
339 # OOM while creating an fts5vocab table. | |
340 # | |
341 reset_db | |
342 do_execsql_test 12.0 { | |
343 CREATE VIRTUAL TABLE ft USING fts5(x); | |
344 } | |
345 faultsim_save_and_close | |
346 do_faultsim_test 12.1 -faults oom-t* -prep { | |
347 faultsim_restore_and_reopen | |
348 db eval { SELECT * FROM sqlite_master } | |
349 } -body { | |
350 db eval { CREATE VIRTUAL TABLE vv USING fts5vocab(ft, 'row') } | |
351 } -test { | |
352 faultsim_test_result {0 {}} | |
353 } | |
354 | |
355 #------------------------------------------------------------------------- | |
356 # OOM while querying an fts5vocab table. | |
357 # | |
358 reset_db | |
359 do_execsql_test 13.0 { | |
360 CREATE VIRTUAL TABLE ft USING fts5(x); | |
361 INSERT INTO ft VALUES('a b'); | |
362 CREATE VIRTUAL TABLE vv USING fts5vocab(ft, 'row'); | |
363 } | |
364 faultsim_save_and_close | |
365 do_faultsim_test 13.1 -faults oom-t* -prep { | |
366 faultsim_restore_and_reopen | |
367 db eval { SELECT * FROM vv } | |
368 } -body { | |
369 db eval { SELECT * FROM vv } | |
370 } -test { | |
371 faultsim_test_result {0 {a 1 1 b 1 1}} | |
372 } | |
373 | |
374 #------------------------------------------------------------------------- | |
375 # OOM in multi-column token query. | |
376 # | |
377 reset_db | |
378 do_execsql_test 13.0 { | |
379 CREATE VIRTUAL TABLE ft USING fts5(x, y, z); | |
380 INSERT INTO ft(ft, rank) VALUES('pgsz', 32); | |
381 INSERT INTO ft VALUES( | |
382 'x x x x x x x x x x x x x x x x', | |
383 'y y y y y y y y y y y y y y y y', | |
384 'z z z z z z z z x x x x x x x x' | |
385 ); | |
386 INSERT INTO ft SELECT * FROM ft; | |
387 INSERT INTO ft SELECT * FROM ft; | |
388 INSERT INTO ft SELECT * FROM ft; | |
389 INSERT INTO ft SELECT * FROM ft; | |
390 } | |
391 faultsim_save_and_close | |
392 do_faultsim_test 13.1 -faults oom-t* -prep { | |
393 faultsim_restore_and_reopen | |
394 db eval { SELECT * FROM ft } | |
395 } -body { | |
396 db eval { SELECT rowid FROM ft WHERE ft MATCH '{x z}: x' } | |
397 } -test { | |
398 faultsim_test_result {0 {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16}} | |
399 } | |
400 | |
401 #------------------------------------------------------------------------- | |
402 # OOM in an "ALTER TABLE RENAME TO" | |
403 # | |
404 reset_db | |
405 do_execsql_test 14.0 { | |
406 CREATE VIRTUAL TABLE "tbl one" USING fts5(x, y, z); | |
407 } | |
408 faultsim_save_and_close | |
409 do_faultsim_test 14.1 -faults oom-t* -prep { | |
410 faultsim_restore_and_reopen | |
411 db eval { SELECT * FROM "tbl one" } | |
412 } -body { | |
413 db eval { ALTER TABLE "tbl one" RENAME TO "tbl two" } | |
414 } -test { | |
415 faultsim_test_result {0 {}} | |
416 } | |
417 | |
418 finish_test | |
419 | |
OLD | NEW |