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