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 |