| OLD | NEW |
| (Empty) |
| 1 # 2010 June 15 | |
| 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 | |
| 13 set testdir [file dirname $argv0] | |
| 14 source $testdir/tester.tcl | |
| 15 source $testdir/lock_common.tcl | |
| 16 source $testdir/malloc_common.tcl | |
| 17 | |
| 18 if {[permutation] == "inmemory_journal"} { | |
| 19 finish_test | |
| 20 return | |
| 21 } | |
| 22 | |
| 23 if {$::tcl_platform(platform)=="windows"} { | |
| 24 finish_test | |
| 25 return | |
| 26 } | |
| 27 | |
| 28 set a_string_counter 1 | |
| 29 proc a_string {n} { | |
| 30 global a_string_counter | |
| 31 incr a_string_counter | |
| 32 string range [string repeat "${a_string_counter}." $n] 1 $n | |
| 33 } | |
| 34 db func a_string a_string | |
| 35 | |
| 36 #------------------------------------------------------------------------- | |
| 37 # Test fault-injection while rolling back a hot-journal file. | |
| 38 # | |
| 39 do_test pagerfault-1-pre1 { | |
| 40 execsql { | |
| 41 PRAGMA journal_mode = DELETE; | |
| 42 PRAGMA cache_size = 10; | |
| 43 CREATE TABLE t1(a UNIQUE, b UNIQUE); | |
| 44 INSERT INTO t1 VALUES(a_string(200), a_string(300)); | |
| 45 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; | |
| 46 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; | |
| 47 BEGIN; | |
| 48 INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1; | |
| 49 INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1; | |
| 50 INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1; | |
| 51 INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1; | |
| 52 } | |
| 53 faultsim_save_and_close | |
| 54 } {} | |
| 55 do_faultsim_test pagerfault-1 -prep { | |
| 56 faultsim_restore_and_reopen | |
| 57 } -body { | |
| 58 execsql { SELECT count(*) FROM t1 } | |
| 59 } -test { | |
| 60 faultsim_test_result {0 4} | |
| 61 faultsim_integrity_check | |
| 62 if {[db one { SELECT count(*) FROM t1 }] != 4} { | |
| 63 error "Database content appears incorrect" | |
| 64 } | |
| 65 } | |
| 66 | |
| 67 #------------------------------------------------------------------------- | |
| 68 # Test fault-injection while rolling back a hot-journal file with a | |
| 69 # page-size different from the current value stored on page 1 of the | |
| 70 # database file. | |
| 71 # | |
| 72 do_test pagerfault-2-pre1 { | |
| 73 testvfs tv -default 1 | |
| 74 tv filter xSync | |
| 75 tv script xSyncCb | |
| 76 proc xSyncCb {filename args} { | |
| 77 if {[string match *journal filename]==0} faultsim_save | |
| 78 } | |
| 79 faultsim_delete_and_reopen | |
| 80 execsql { | |
| 81 PRAGMA page_size = 4096; | |
| 82 BEGIN; | |
| 83 CREATE TABLE abc(a, b, c); | |
| 84 INSERT INTO abc VALUES('o', 't', 't'); | |
| 85 INSERT INTO abc VALUES('f', 'f', 's'); | |
| 86 INSERT INTO abc SELECT * FROM abc; -- 4 | |
| 87 INSERT INTO abc SELECT * FROM abc; -- 8 | |
| 88 INSERT INTO abc SELECT * FROM abc; -- 16 | |
| 89 INSERT INTO abc SELECT * FROM abc; -- 32 | |
| 90 INSERT INTO abc SELECT * FROM abc; -- 64 | |
| 91 INSERT INTO abc SELECT * FROM abc; -- 128 | |
| 92 INSERT INTO abc SELECT * FROM abc; -- 256 | |
| 93 COMMIT; | |
| 94 PRAGMA page_size = 1024; | |
| 95 VACUUM; | |
| 96 } | |
| 97 db close | |
| 98 tv delete | |
| 99 } {} | |
| 100 do_faultsim_test pagerfault-2 -prep { | |
| 101 faultsim_restore_and_reopen | |
| 102 } -body { | |
| 103 execsql { SELECT * FROM abc } | |
| 104 } -test { | |
| 105 set answer [split [string repeat "ottffs" 128] ""] | |
| 106 faultsim_test_result [list 0 $answer] | |
| 107 faultsim_integrity_check | |
| 108 set res [db eval { SELECT * FROM abc }] | |
| 109 if {$res != $answer} { error "Database content appears incorrect ($res)" } | |
| 110 } | |
| 111 | |
| 112 #------------------------------------------------------------------------- | |
| 113 # Test fault-injection while rolling back hot-journals that were created | |
| 114 # as part of a multi-file transaction. | |
| 115 # | |
| 116 do_test pagerfault-3-pre1 { | |
| 117 testvfs tstvfs -default 1 | |
| 118 tstvfs filter xDelete | |
| 119 tstvfs script xDeleteCallback | |
| 120 | |
| 121 proc xDeleteCallback {method file args} { | |
| 122 set file [file tail $file] | |
| 123 if { [string match *mj* $file] } { faultsim_save } | |
| 124 } | |
| 125 | |
| 126 faultsim_delete_and_reopen | |
| 127 db func a_string a_string | |
| 128 | |
| 129 execsql { | |
| 130 ATTACH 'test.db2' AS aux; | |
| 131 PRAGMA journal_mode = DELETE; | |
| 132 PRAGMA main.cache_size = 10; | |
| 133 PRAGMA aux.cache_size = 10; | |
| 134 | |
| 135 CREATE TABLE t1(a UNIQUE, b UNIQUE); | |
| 136 CREATE TABLE aux.t2(a UNIQUE, b UNIQUE); | |
| 137 INSERT INTO t1 VALUES(a_string(200), a_string(300)); | |
| 138 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; | |
| 139 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; | |
| 140 INSERT INTO t2 SELECT * FROM t1; | |
| 141 | |
| 142 BEGIN; | |
| 143 INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1; | |
| 144 INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1; | |
| 145 INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1; | |
| 146 INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1; | |
| 147 REPLACE INTO t2 SELECT * FROM t1; | |
| 148 COMMIT; | |
| 149 } | |
| 150 | |
| 151 db close | |
| 152 tstvfs delete | |
| 153 } {} | |
| 154 do_faultsim_test pagerfault-3 -prep { | |
| 155 faultsim_restore_and_reopen | |
| 156 } -body { | |
| 157 execsql { | |
| 158 ATTACH 'test.db2' AS aux; | |
| 159 SELECT count(*) FROM t2; | |
| 160 SELECT count(*) FROM t1; | |
| 161 } | |
| 162 } -test { | |
| 163 faultsim_test_result {0 {4 4}} {1 {unable to open database: test.db2}} | |
| 164 faultsim_integrity_check | |
| 165 catchsql { ATTACH 'test.db2' AS aux } | |
| 166 if {[db one { SELECT count(*) FROM t1 }] != 4 | |
| 167 || [db one { SELECT count(*) FROM t2 }] != 4 | |
| 168 } { | |
| 169 error "Database content appears incorrect" | |
| 170 } | |
| 171 } | |
| 172 | |
| 173 #------------------------------------------------------------------------- | |
| 174 # Test fault-injection as part of a vanilla, no-transaction, INSERT | |
| 175 # statement. | |
| 176 # | |
| 177 do_faultsim_test pagerfault-4 -prep { | |
| 178 faultsim_delete_and_reopen | |
| 179 } -body { | |
| 180 execsql { | |
| 181 CREATE TABLE x(y); | |
| 182 INSERT INTO x VALUES('z'); | |
| 183 SELECT * FROM x; | |
| 184 } | |
| 185 } -test { | |
| 186 faultsim_test_result {0 z} | |
| 187 faultsim_integrity_check | |
| 188 } | |
| 189 | |
| 190 #------------------------------------------------------------------------- | |
| 191 # Test fault-injection as part of a commit when using journal_mode=PERSIST. | |
| 192 # Three different cases: | |
| 193 # | |
| 194 # pagerfault-5.1: With no journal_size_limit configured. | |
| 195 # pagerfault-5.2: With a journal_size_limit configured. | |
| 196 # pagerfault-5.4: Multi-file transaction. One connection has a | |
| 197 # journal_size_limit of 0, the other has no limit. | |
| 198 # | |
| 199 do_test pagerfault-5-pre1 { | |
| 200 faultsim_delete_and_reopen | |
| 201 db func a_string a_string | |
| 202 execsql { | |
| 203 CREATE TABLE t1(a UNIQUE, b UNIQUE); | |
| 204 INSERT INTO t1 VALUES(a_string(200), a_string(300)); | |
| 205 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; | |
| 206 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; | |
| 207 } | |
| 208 faultsim_save_and_close | |
| 209 } {} | |
| 210 do_faultsim_test pagerfault-5.1 -prep { | |
| 211 faultsim_restore_and_reopen | |
| 212 db func a_string a_string | |
| 213 execsql { PRAGMA journal_mode = PERSIST } | |
| 214 } -body { | |
| 215 execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 } | |
| 216 } -test { | |
| 217 faultsim_test_result {0 {}} | |
| 218 faultsim_integrity_check | |
| 219 } | |
| 220 do_faultsim_test pagerfault-5.2 -prep { | |
| 221 faultsim_restore_and_reopen | |
| 222 db func a_string a_string | |
| 223 execsql { | |
| 224 PRAGMA journal_mode = PERSIST; | |
| 225 PRAGMA journal_size_limit = 2048; | |
| 226 } | |
| 227 } -body { | |
| 228 execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 } | |
| 229 } -test { | |
| 230 faultsim_test_result {0 {}} | |
| 231 faultsim_integrity_check | |
| 232 } | |
| 233 do_faultsim_test pagerfault-5.3 -faults oom-transient -prep { | |
| 234 faultsim_restore_and_reopen | |
| 235 db func a_string a_string | |
| 236 forcedelete test2.db test2.db-journal test2.db-wal | |
| 237 execsql { | |
| 238 PRAGMA journal_mode = PERSIST; | |
| 239 ATTACH 'test2.db' AS aux; | |
| 240 PRAGMA aux.journal_mode = PERSIST; | |
| 241 PRAGMA aux.journal_size_limit = 0; | |
| 242 } | |
| 243 } -body { | |
| 244 execsql { | |
| 245 BEGIN; | |
| 246 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; | |
| 247 CREATE TABLE aux.t2 AS SELECT * FROM t1; | |
| 248 COMMIT; | |
| 249 } | |
| 250 } -test { | |
| 251 faultsim_test_result {0 {}} | |
| 252 | |
| 253 catchsql { COMMIT } | |
| 254 catchsql { ROLLBACK } | |
| 255 | |
| 256 faultsim_integrity_check | |
| 257 set res "" | |
| 258 set rc [catch { set res [db one { PRAGMA aux.integrity_check }] }] | |
| 259 if {$rc!=0 || $res != "ok"} {error "integrity-check problem:$rc $res"} | |
| 260 } | |
| 261 | |
| 262 #------------------------------------------------------------------------- | |
| 263 # Test fault-injection as part of a commit when using | |
| 264 # journal_mode=TRUNCATE. | |
| 265 # | |
| 266 do_test pagerfault-6-pre1 { | |
| 267 faultsim_delete_and_reopen | |
| 268 db func a_string a_string | |
| 269 execsql { | |
| 270 CREATE TABLE t1(a UNIQUE, b UNIQUE); | |
| 271 INSERT INTO t1 VALUES(a_string(200), a_string(300)); | |
| 272 } | |
| 273 faultsim_save_and_close | |
| 274 } {} | |
| 275 | |
| 276 do_faultsim_test pagerfault-6.1 -prep { | |
| 277 faultsim_restore_and_reopen | |
| 278 db func a_string a_string | |
| 279 execsql { PRAGMA journal_mode = TRUNCATE } | |
| 280 } -body { | |
| 281 execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 } | |
| 282 execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 } | |
| 283 } -test { | |
| 284 faultsim_test_result {0 {}} | |
| 285 faultsim_integrity_check | |
| 286 } | |
| 287 | |
| 288 # The unix vfs xAccess() method considers a file zero bytes in size to | |
| 289 # "not exist". This proc overrides that behaviour so that a zero length | |
| 290 # file is considered to exist. | |
| 291 # | |
| 292 proc xAccess {method filename op args} { | |
| 293 if {$op != "SQLITE_ACCESS_EXISTS"} { return "" } | |
| 294 return [file exists $filename] | |
| 295 } | |
| 296 do_faultsim_test pagerfault-6.2 -faults cantopen-* -prep { | |
| 297 shmfault filter xAccess | |
| 298 shmfault script xAccess | |
| 299 | |
| 300 faultsim_restore_and_reopen | |
| 301 db func a_string a_string | |
| 302 execsql { PRAGMA journal_mode = TRUNCATE } | |
| 303 } -body { | |
| 304 execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 } | |
| 305 execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 } | |
| 306 } -test { | |
| 307 faultsim_test_result {0 {}} | |
| 308 faultsim_integrity_check | |
| 309 } | |
| 310 | |
| 311 # The following was an attempt to get a bitvec malloc to fail. Didn't work. | |
| 312 # | |
| 313 # do_test pagerfault-6-pre1 { | |
| 314 # faultsim_delete_and_reopen | |
| 315 # execsql { | |
| 316 # CREATE TABLE t1(x, y, UNIQUE(x, y)); | |
| 317 # INSERT INTO t1 VALUES(1, randomblob(1501)); | |
| 318 # INSERT INTO t1 VALUES(2, randomblob(1502)); | |
| 319 # INSERT INTO t1 VALUES(3, randomblob(1503)); | |
| 320 # INSERT INTO t1 VALUES(4, randomblob(1504)); | |
| 321 # INSERT INTO t1 | |
| 322 # SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1; | |
| 323 # INSERT INTO t1 | |
| 324 # SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1; | |
| 325 # INSERT INTO t1 | |
| 326 # SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1; | |
| 327 # INSERT INTO t1 | |
| 328 # SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1; | |
| 329 # } | |
| 330 # faultsim_save_and_close | |
| 331 # } {} | |
| 332 # do_faultsim_test pagerfault-6 -prep { | |
| 333 # faultsim_restore_and_reopen | |
| 334 # } -body { | |
| 335 # execsql { | |
| 336 # BEGIN; | |
| 337 # UPDATE t1 SET x=x+4 WHERE x=1; | |
| 338 # SAVEPOINT one; | |
| 339 # UPDATE t1 SET x=x+4 WHERE x=2; | |
| 340 # SAVEPOINT three; | |
| 341 # UPDATE t1 SET x=x+4 WHERE x=3; | |
| 342 # SAVEPOINT four; | |
| 343 # UPDATE t1 SET x=x+4 WHERE x=4; | |
| 344 # RELEASE three; | |
| 345 # COMMIT; | |
| 346 # SELECT DISTINCT x FROM t1; | |
| 347 # } | |
| 348 # } -test { | |
| 349 # faultsim_test_result {0 {5 6 7 8}} | |
| 350 # faultsim_integrity_check | |
| 351 # } | |
| 352 # | |
| 353 | |
| 354 # This is designed to provoke a special case in the pager code: | |
| 355 # | |
| 356 # If an error (specifically, a FULL or IOERR error) occurs while writing a | |
| 357 # dirty page to the file-system in order to free up memory, the pager enters | |
| 358 # the "error state". An IO error causes SQLite to roll back the current | |
| 359 # transaction (exiting the error state). A FULL error, however, may only | |
| 360 # rollback the current statement. | |
| 361 # | |
| 362 # This block tests that nothing goes wrong if a FULL error occurs while | |
| 363 # writing a dirty page out to free memory from within a statement that has | |
| 364 # opened a statement transaction. | |
| 365 # | |
| 366 do_test pagerfault-7-pre1 { | |
| 367 faultsim_delete_and_reopen | |
| 368 execsql { | |
| 369 CREATE TABLE t2(a INTEGER PRIMARY KEY, b); | |
| 370 BEGIN; | |
| 371 INSERT INTO t2 VALUES(NULL, randomblob(1500)); | |
| 372 INSERT INTO t2 VALUES(NULL, randomblob(1500)); | |
| 373 INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2; -- 4 | |
| 374 INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2; -- 8 | |
| 375 INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2; -- 16 | |
| 376 INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2; -- 32 | |
| 377 INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2; -- 64 | |
| 378 COMMIT; | |
| 379 CREATE TABLE t1(a PRIMARY KEY, b); | |
| 380 INSERT INTO t1 SELECT * FROM t2; | |
| 381 DROP TABLE t2; | |
| 382 } | |
| 383 faultsim_save_and_close | |
| 384 } {} | |
| 385 do_faultsim_test pagerfault-7 -prep { | |
| 386 faultsim_restore_and_reopen | |
| 387 execsql { | |
| 388 PRAGMA cache_size = 10; | |
| 389 BEGIN; | |
| 390 UPDATE t1 SET b = randomblob(1500); | |
| 391 } | |
| 392 } -body { | |
| 393 execsql { UPDATE t1 SET a = 65, b = randomblob(1500) WHERE (a+1)>200 } | |
| 394 execsql COMMIT | |
| 395 } -test { | |
| 396 faultsim_test_result {0 {}} | |
| 397 faultsim_integrity_check | |
| 398 } | |
| 399 | |
| 400 do_test pagerfault-8-pre1 { | |
| 401 faultsim_delete_and_reopen | |
| 402 execsql { | |
| 403 PRAGMA auto_vacuum = 1; | |
| 404 CREATE TABLE t1(a INTEGER PRIMARY KEY, b); | |
| 405 BEGIN; | |
| 406 INSERT INTO t1 VALUES(NULL, randomblob(1500)); | |
| 407 INSERT INTO t1 VALUES(NULL, randomblob(1500)); | |
| 408 INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1; -- 4 | |
| 409 INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1; -- 8 | |
| 410 INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1; -- 16 | |
| 411 INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1; -- 32 | |
| 412 INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1; -- 64 | |
| 413 COMMIT; | |
| 414 } | |
| 415 faultsim_save_and_close | |
| 416 set filesize [file size test.db] | |
| 417 set {} {} | |
| 418 } {} | |
| 419 do_test pagerfault-8-pre2 { | |
| 420 faultsim_restore_and_reopen | |
| 421 execsql { DELETE FROM t1 WHERE a>32 } | |
| 422 expr {[file size test.db] < $filesize} | |
| 423 } {1} | |
| 424 do_faultsim_test pagerfault-8 -prep { | |
| 425 faultsim_restore_and_reopen | |
| 426 execsql { | |
| 427 BEGIN; | |
| 428 DELETE FROM t1 WHERE a>32; | |
| 429 } | |
| 430 } -body { | |
| 431 execsql COMMIT | |
| 432 } -test { | |
| 433 faultsim_test_result {0 {}} | |
| 434 faultsim_integrity_check | |
| 435 } | |
| 436 | |
| 437 #------------------------------------------------------------------------- | |
| 438 # This test case is specially designed so that during a savepoint | |
| 439 # rollback, a new cache entry must be allocated (see comments surrounding | |
| 440 # the call to sqlite3PagerAcquire() from within pager_playback_one_page() | |
| 441 # for details). Test the effects of injecting an OOM at this point. | |
| 442 # | |
| 443 do_test pagerfault-9-pre1 { | |
| 444 faultsim_delete_and_reopen | |
| 445 execsql { | |
| 446 PRAGMA auto_vacuum = incremental; | |
| 447 CREATE TABLE t1(x); | |
| 448 CREATE TABLE t2(y); | |
| 449 CREATE TABLE t3(z); | |
| 450 | |
| 451 INSERT INTO t1 VALUES(randomblob(900)); | |
| 452 INSERT INTO t1 VALUES(randomblob(900)); | |
| 453 DELETE FROM t1; | |
| 454 } | |
| 455 faultsim_save_and_close | |
| 456 } {} | |
| 457 do_faultsim_test pagerfault-9.1 -prep { | |
| 458 faultsim_restore_and_reopen | |
| 459 execsql { | |
| 460 BEGIN; | |
| 461 INSERT INTO t1 VALUES(randomblob(900)); | |
| 462 INSERT INTO t1 VALUES(randomblob(900)); | |
| 463 DROP TABLE t3; | |
| 464 DROP TABLE t2; | |
| 465 SAVEPOINT abc; | |
| 466 PRAGMA incremental_vacuum; | |
| 467 } | |
| 468 } -body { | |
| 469 execsql { | |
| 470 ROLLBACK TO abc; | |
| 471 COMMIT; | |
| 472 PRAGMA freelist_count | |
| 473 } | |
| 474 } -test { | |
| 475 faultsim_test_result {0 2} | |
| 476 faultsim_integrity_check | |
| 477 | |
| 478 set sl [db one { SELECT COALESCE(sum(length(x)), 'null') FROM t1 }] | |
| 479 if {$sl!="null" && $sl!=1800} { | |
| 480 error "Content looks no good... ($sl)" | |
| 481 } | |
| 482 } | |
| 483 | |
| 484 #------------------------------------------------------------------------- | |
| 485 # Test fault injection with a temporary database file. | |
| 486 # | |
| 487 foreach v {a b} { | |
| 488 do_faultsim_test pagerfault-10$v -prep { | |
| 489 sqlite3 db "" | |
| 490 db func a_string a_string; | |
| 491 execsql { | |
| 492 PRAGMA cache_size = 10; | |
| 493 BEGIN; | |
| 494 CREATE TABLE xx(a, b, UNIQUE(a, b)); | |
| 495 INSERT INTO xx VALUES(a_string(200), a_string(200)); | |
| 496 INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx; | |
| 497 INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx; | |
| 498 INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx; | |
| 499 INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx; | |
| 500 COMMIT; | |
| 501 } | |
| 502 } -body { | |
| 503 execsql { UPDATE xx SET a = a_string(300) } | |
| 504 } -test { | |
| 505 faultsim_test_result {0 {}} | |
| 506 if {$::v == "b"} { execsql { PRAGMA journal_mode = TRUNCATE } } | |
| 507 faultsim_integrity_check | |
| 508 faultsim_integrity_check | |
| 509 } | |
| 510 } | |
| 511 | |
| 512 #------------------------------------------------------------------------- | |
| 513 # Test fault injection with transaction savepoints (savepoints created | |
| 514 # when a SAVEPOINT command is executed outside of any other savepoint | |
| 515 # or transaction context). | |
| 516 # | |
| 517 do_test pagerfault-9-pre1 { | |
| 518 faultsim_delete_and_reopen | |
| 519 db func a_string a_string; | |
| 520 execsql { | |
| 521 PRAGMA auto_vacuum = on; | |
| 522 CREATE TABLE t1(x UNIQUE); | |
| 523 CREATE TABLE t2(y UNIQUE); | |
| 524 CREATE TABLE t3(z UNIQUE); | |
| 525 BEGIN; | |
| 526 INSERT INTO t1 VALUES(a_string(202)); | |
| 527 INSERT INTO t2 VALUES(a_string(203)); | |
| 528 INSERT INTO t3 VALUES(a_string(204)); | |
| 529 INSERT INTO t1 SELECT a_string(202) FROM t1; | |
| 530 INSERT INTO t1 SELECT a_string(203) FROM t1; | |
| 531 INSERT INTO t1 SELECT a_string(204) FROM t1; | |
| 532 INSERT INTO t1 SELECT a_string(205) FROM t1; | |
| 533 INSERT INTO t2 SELECT a_string(length(x)) FROM t1; | |
| 534 INSERT INTO t3 SELECT a_string(length(x)) FROM t1; | |
| 535 COMMIT; | |
| 536 } | |
| 537 faultsim_save_and_close | |
| 538 } {} | |
| 539 do_faultsim_test pagerfault-11 -prep { | |
| 540 faultsim_restore_and_reopen | |
| 541 execsql { PRAGMA cache_size = 10 } | |
| 542 } -body { | |
| 543 execsql { | |
| 544 SAVEPOINT trans; | |
| 545 UPDATE t2 SET y = y||'2'; | |
| 546 INSERT INTO t3 SELECT * FROM t2; | |
| 547 DELETE FROM t1; | |
| 548 ROLLBACK TO trans; | |
| 549 UPDATE t1 SET x = x||'3'; | |
| 550 INSERT INTO t2 SELECT * FROM t1; | |
| 551 DELETE FROM t3; | |
| 552 RELEASE trans; | |
| 553 } | |
| 554 } -test { | |
| 555 faultsim_test_result {0 {}} | |
| 556 faultsim_integrity_check | |
| 557 } | |
| 558 | |
| 559 | |
| 560 #------------------------------------------------------------------------- | |
| 561 # Test fault injection when writing to a database file that resides on | |
| 562 # a file-system with a sector-size larger than the database page-size. | |
| 563 # | |
| 564 do_test pagerfault-12-pre1 { | |
| 565 testvfs ss_layer -default 1 | |
| 566 ss_layer sectorsize 4096 | |
| 567 faultsim_delete_and_reopen | |
| 568 db func a_string a_string; | |
| 569 | |
| 570 execsql { | |
| 571 PRAGMA page_size = 1024; | |
| 572 PRAGMA journal_mode = PERSIST; | |
| 573 PRAGMA cache_size = 10; | |
| 574 BEGIN; | |
| 575 CREATE TABLE t1(x, y UNIQUE); | |
| 576 INSERT INTO t1 VALUES(a_string(333), a_string(444)); | |
| 577 INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1; | |
| 578 INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1; | |
| 579 INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1; | |
| 580 INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1; | |
| 581 INSERT INTO t1 SELECT a_string(44), a_string(55) FROM t1 LIMIT 13; | |
| 582 COMMIT; | |
| 583 } | |
| 584 faultsim_save_and_close | |
| 585 } {} | |
| 586 | |
| 587 do_faultsim_test pagerfault-12a -prep { | |
| 588 faultsim_restore_and_reopen | |
| 589 execsql { PRAGMA cache_size = 10 } | |
| 590 db func a_string a_string; | |
| 591 } -body { | |
| 592 execsql { | |
| 593 UPDATE t1 SET x = a_string(length(x)), y = a_string(length(y)); | |
| 594 } | |
| 595 } -test { | |
| 596 faultsim_test_result {0 {}} | |
| 597 faultsim_integrity_check | |
| 598 } | |
| 599 | |
| 600 do_test pagerfault-12-pre2 { | |
| 601 faultsim_restore_and_reopen | |
| 602 execsql { | |
| 603 CREATE TABLE t2 AS SELECT * FROM t1 LIMIT 10; | |
| 604 } | |
| 605 faultsim_save_and_close | |
| 606 } {} | |
| 607 do_faultsim_test pagerfault-12b -prep { | |
| 608 faultsim_restore_and_reopen | |
| 609 db func a_string a_string; | |
| 610 execsql { SELECT * FROM t1 } | |
| 611 } -body { | |
| 612 set sql(1) { UPDATE t2 SET x = a_string(280) } | |
| 613 set sql(2) { UPDATE t1 SET x = a_string(280) WHERE rowid = 5 } | |
| 614 | |
| 615 db eval { SELECT rowid FROM t1 LIMIT 2 } { db eval $sql($rowid) } | |
| 616 | |
| 617 } -test { | |
| 618 faultsim_test_result {0 {}} | |
| 619 faultsim_integrity_check | |
| 620 } | |
| 621 | |
| 622 catch { db close } | |
| 623 ss_layer delete | |
| 624 | |
| 625 | |
| 626 #------------------------------------------------------------------------- | |
| 627 # Test fault injection when SQLite opens a database where the size of the | |
| 628 # database file is zero bytes but the accompanying journal file is larger | |
| 629 # than that. In this scenario SQLite should delete the journal file | |
| 630 # without rolling it back, even if it is in all other respects a valid | |
| 631 # hot-journal file. | |
| 632 # | |
| 633 do_test pagerfault-13-pre1 { | |
| 634 faultsim_delete_and_reopen | |
| 635 db func a_string a_string; | |
| 636 execsql { | |
| 637 PRAGMA journal_mode = PERSIST; | |
| 638 BEGIN; | |
| 639 CREATE TABLE t1(x, y UNIQUE); | |
| 640 INSERT INTO t1 VALUES(a_string(333), a_string(444)); | |
| 641 COMMIT; | |
| 642 } | |
| 643 db close | |
| 644 forcedelete test.db | |
| 645 faultsim_save | |
| 646 } {} | |
| 647 do_faultsim_test pagerfault-13 -prep { | |
| 648 faultsim_restore_and_reopen | |
| 649 } -body { | |
| 650 execsql { CREATE TABLE xx(a, b) } | |
| 651 } -test { | |
| 652 faultsim_test_result {0 {}} | |
| 653 } | |
| 654 | |
| 655 #--------------------------------------------------------------------------- | |
| 656 # Test fault injection into a small backup operation. | |
| 657 # | |
| 658 do_test pagerfault-14-pre1 { | |
| 659 faultsim_delete_and_reopen | |
| 660 db func a_string a_string; | |
| 661 execsql { | |
| 662 PRAGMA journal_mode = PERSIST; | |
| 663 ATTACH 'test.db2' AS two; | |
| 664 BEGIN; | |
| 665 CREATE TABLE t1(x, y UNIQUE); | |
| 666 CREATE TABLE two.t2(x, y UNIQUE); | |
| 667 INSERT INTO t1 VALUES(a_string(333), a_string(444)); | |
| 668 INSERT INTO t2 VALUES(a_string(333), a_string(444)); | |
| 669 COMMIT; | |
| 670 } | |
| 671 faultsim_save_and_close | |
| 672 } {} | |
| 673 | |
| 674 do_faultsim_test pagerfault-14a -prep { | |
| 675 faultsim_restore_and_reopen | |
| 676 } -body { | |
| 677 if {[catch {db backup test.db2} msg]} { error [regsub {.*: } $msg {}] } | |
| 678 } -test { | |
| 679 faultsim_test_result {0 {}} {1 {}} {1 {SQL logic error or missing database}} | |
| 680 } | |
| 681 | |
| 682 # If TEMP_STORE is 2 or greater, then the database [db2] will be created | |
| 683 # as an in-memory database. This test will not work in that case, as it | |
| 684 # is not possible to change the page-size of an in-memory database. Even | |
| 685 # using the backup API. | |
| 686 # | |
| 687 if {$TEMP_STORE<2} { | |
| 688 do_faultsim_test pagerfault-14b -prep { | |
| 689 catch { db2 close } | |
| 690 faultsim_restore_and_reopen | |
| 691 sqlite3 db2 "" | |
| 692 db2 eval { PRAGMA page_size = 4096; CREATE TABLE xx(a) } | |
| 693 } -body { | |
| 694 sqlite3_backup B db2 main db main | |
| 695 B step 200 | |
| 696 set rc [B finish] | |
| 697 if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR} | |
| 698 if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] } | |
| 699 set {} {} | |
| 700 } -test { | |
| 701 faultsim_test_result {0 {}} {1 {sqlite3_backup_init() failed}} | |
| 702 } | |
| 703 } | |
| 704 | |
| 705 do_faultsim_test pagerfault-14c -prep { | |
| 706 catch { db2 close } | |
| 707 faultsim_restore_and_reopen | |
| 708 sqlite3 db2 test.db2 | |
| 709 db2 eval { | |
| 710 PRAGMA synchronous = off; | |
| 711 PRAGMA page_size = 4096; | |
| 712 CREATE TABLE xx(a); | |
| 713 } | |
| 714 } -body { | |
| 715 sqlite3_backup B db2 main db main | |
| 716 B step 200 | |
| 717 set rc [B finish] | |
| 718 if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR} | |
| 719 if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] } | |
| 720 set {} {} | |
| 721 } -test { | |
| 722 faultsim_test_result {0 {}} {1 {sqlite3_backup_init() failed}} | |
| 723 } | |
| 724 | |
| 725 do_test pagerfault-15-pre1 { | |
| 726 faultsim_delete_and_reopen | |
| 727 db func a_string a_string; | |
| 728 execsql { | |
| 729 BEGIN; | |
| 730 CREATE TABLE t1(x, y UNIQUE); | |
| 731 INSERT INTO t1 VALUES(a_string(11), a_string(22)); | |
| 732 INSERT INTO t1 VALUES(a_string(11), a_string(22)); | |
| 733 COMMIT; | |
| 734 } | |
| 735 faultsim_save_and_close | |
| 736 } {} | |
| 737 do_faultsim_test pagerfault-15 -prep { | |
| 738 faultsim_restore_and_reopen | |
| 739 db func a_string a_string; | |
| 740 } -body { | |
| 741 db eval { SELECT * FROM t1 LIMIT 1 } { | |
| 742 execsql { | |
| 743 BEGIN; INSERT INTO t1 VALUES(a_string(333), a_string(555)); COMMIT; | |
| 744 BEGIN; INSERT INTO t1 VALUES(a_string(333), a_string(555)); COMMIT; | |
| 745 } | |
| 746 } | |
| 747 } -test { | |
| 748 faultsim_test_result {0 {}} | |
| 749 faultsim_integrity_check | |
| 750 } | |
| 751 | |
| 752 | |
| 753 do_test pagerfault-16-pre1 { | |
| 754 faultsim_delete_and_reopen | |
| 755 execsql { CREATE TABLE t1(x, y UNIQUE) } | |
| 756 faultsim_save_and_close | |
| 757 } {} | |
| 758 do_faultsim_test pagerfault-16 -prep { | |
| 759 faultsim_restore_and_reopen | |
| 760 } -body { | |
| 761 execsql { | |
| 762 PRAGMA locking_mode = exclusive; | |
| 763 PRAGMA journal_mode = wal; | |
| 764 INSERT INTO t1 VALUES(1, 2); | |
| 765 INSERT INTO t1 VALUES(3, 4); | |
| 766 PRAGMA journal_mode = delete; | |
| 767 INSERT INTO t1 VALUES(4, 5); | |
| 768 PRAGMA journal_mode = wal; | |
| 769 INSERT INTO t1 VALUES(6, 7); | |
| 770 PRAGMA journal_mode = persist; | |
| 771 INSERT INTO t1 VALUES(8, 9); | |
| 772 } | |
| 773 } -test { | |
| 774 faultsim_test_result {0 {exclusive wal delete wal persist}} | |
| 775 faultsim_integrity_check | |
| 776 } | |
| 777 | |
| 778 | |
| 779 #------------------------------------------------------------------------- | |
| 780 # Test fault injection while changing into and out of WAL mode. | |
| 781 # | |
| 782 do_test pagerfault-17-pre1 { | |
| 783 faultsim_delete_and_reopen | |
| 784 execsql { | |
| 785 CREATE TABLE t1(a PRIMARY KEY, b); | |
| 786 INSERT INTO t1 VALUES(1862, 'Botha'); | |
| 787 INSERT INTO t1 VALUES(1870, 'Smuts'); | |
| 788 INSERT INTO t1 VALUES(1866, 'Hertzog'); | |
| 789 } | |
| 790 faultsim_save_and_close | |
| 791 } {} | |
| 792 do_faultsim_test pagerfault-17a -prep { | |
| 793 faultsim_restore_and_reopen | |
| 794 } -body { | |
| 795 execsql { | |
| 796 PRAGMA journal_mode = wal; | |
| 797 PRAGMA journal_mode = delete; | |
| 798 } | |
| 799 } -test { | |
| 800 faultsim_test_result {0 {wal delete}} | |
| 801 faultsim_integrity_check | |
| 802 } | |
| 803 do_faultsim_test pagerfault-17b -prep { | |
| 804 faultsim_restore_and_reopen | |
| 805 execsql { PRAGMA synchronous = OFF } | |
| 806 } -body { | |
| 807 execsql { | |
| 808 PRAGMA journal_mode = wal; | |
| 809 INSERT INTO t1 VALUES(22, 'Clarke'); | |
| 810 PRAGMA journal_mode = delete; | |
| 811 } | |
| 812 } -test { | |
| 813 faultsim_test_result {0 {wal delete}} | |
| 814 faultsim_integrity_check | |
| 815 } | |
| 816 do_faultsim_test pagerfault-17c -prep { | |
| 817 faultsim_restore_and_reopen | |
| 818 execsql { | |
| 819 PRAGMA locking_mode = exclusive; | |
| 820 PRAGMA journal_mode = wal; | |
| 821 } | |
| 822 } -body { | |
| 823 execsql { PRAGMA journal_mode = delete } | |
| 824 } -test { | |
| 825 faultsim_test_result {0 delete} | |
| 826 faultsim_integrity_check | |
| 827 } | |
| 828 do_faultsim_test pagerfault-17d -prep { | |
| 829 catch { db2 close } | |
| 830 faultsim_restore_and_reopen | |
| 831 sqlite3 db2 test.db | |
| 832 execsql { PRAGMA journal_mode = delete } | |
| 833 execsql { PRAGMA journal_mode = wal } | |
| 834 execsql { INSERT INTO t1 VALUES(99, 'Bradman') } db2 | |
| 835 } -body { | |
| 836 execsql { PRAGMA journal_mode = delete } | |
| 837 } -test { | |
| 838 faultsim_test_result {1 {database is locked}} | |
| 839 faultsim_integrity_check | |
| 840 } | |
| 841 do_faultsim_test pagerfault-17e -prep { | |
| 842 catch { db2 close } | |
| 843 faultsim_restore_and_reopen | |
| 844 sqlite3 db2 test.db | |
| 845 execsql { PRAGMA journal_mode = delete } | |
| 846 execsql { PRAGMA journal_mode = wal } | |
| 847 set ::chan [launch_testfixture] | |
| 848 testfixture $::chan { | |
| 849 sqlite3 db test.db | |
| 850 db eval { INSERT INTO t1 VALUES(101, 'Latham') } | |
| 851 } | |
| 852 catch { testfixture $::chan sqlite_abort } | |
| 853 catch { close $::chan } | |
| 854 } -body { | |
| 855 execsql { PRAGMA journal_mode = delete } | |
| 856 } -test { | |
| 857 faultsim_test_result {0 delete} | |
| 858 faultsim_integrity_check | |
| 859 } | |
| 860 | |
| 861 #------------------------------------------------------------------------- | |
| 862 # Test fault-injection when changing from journal_mode=persist to | |
| 863 # journal_mode=delete (this involves deleting the journal file). | |
| 864 # | |
| 865 do_test pagerfault-18-pre1 { | |
| 866 faultsim_delete_and_reopen | |
| 867 execsql { | |
| 868 CREATE TABLE qq(x); | |
| 869 INSERT INTO qq VALUES('Herbert'); | |
| 870 INSERT INTO qq VALUES('Macalister'); | |
| 871 INSERT INTO qq VALUES('Mackenzie'); | |
| 872 INSERT INTO qq VALUES('Lilley'); | |
| 873 INSERT INTO qq VALUES('Palmer'); | |
| 874 } | |
| 875 faultsim_save_and_close | |
| 876 } {} | |
| 877 do_faultsim_test pagerfault-18 -prep { | |
| 878 faultsim_restore_and_reopen | |
| 879 execsql { | |
| 880 PRAGMA journal_mode = PERSIST; | |
| 881 INSERT INTO qq VALUES('Beatty'); | |
| 882 } | |
| 883 } -body { | |
| 884 execsql { PRAGMA journal_mode = delete } | |
| 885 } -test { | |
| 886 faultsim_test_result {0 delete} | |
| 887 faultsim_integrity_check | |
| 888 } | |
| 889 | |
| 890 do_faultsim_test pagerfault-19a -prep { | |
| 891 sqlite3 db :memory: | |
| 892 db func a_string a_string | |
| 893 execsql { | |
| 894 PRAGMA auto_vacuum = FULL; | |
| 895 BEGIN; | |
| 896 CREATE TABLE t1(a, b); | |
| 897 INSERT INTO t1 VALUES(a_string(5000), a_string(6000)); | |
| 898 COMMIT; | |
| 899 } | |
| 900 } -body { | |
| 901 execsql { | |
| 902 CREATE TABLE t2(a, b); | |
| 903 INSERT INTO t2 SELECT * FROM t1; | |
| 904 DELETE FROM t1; | |
| 905 } | |
| 906 } -test { | |
| 907 faultsim_test_result {0 {}} | |
| 908 } | |
| 909 | |
| 910 do_test pagerfault-19-pre1 { | |
| 911 faultsim_delete_and_reopen | |
| 912 execsql { | |
| 913 PRAGMA auto_vacuum = FULL; | |
| 914 CREATE TABLE t1(x); INSERT INTO t1 VALUES(1); | |
| 915 CREATE TABLE t2(x); INSERT INTO t2 VALUES(2); | |
| 916 CREATE TABLE t3(x); INSERT INTO t3 VALUES(3); | |
| 917 CREATE TABLE t4(x); INSERT INTO t4 VALUES(4); | |
| 918 CREATE TABLE t5(x); INSERT INTO t5 VALUES(5); | |
| 919 CREATE TABLE t6(x); INSERT INTO t6 VALUES(6); | |
| 920 } | |
| 921 faultsim_save_and_close | |
| 922 } {} | |
| 923 do_faultsim_test pagerfault-19b -prep { | |
| 924 faultsim_restore_and_reopen | |
| 925 } -body { | |
| 926 execsql { | |
| 927 BEGIN; | |
| 928 UPDATE t4 SET x = x+1; | |
| 929 UPDATE t6 SET x = x+1; | |
| 930 SAVEPOINT one; | |
| 931 UPDATE t3 SET x = x+1; | |
| 932 SAVEPOINT two; | |
| 933 DROP TABLE t2; | |
| 934 ROLLBACK TO one; | |
| 935 COMMIT; | |
| 936 SELECT * FROM t3; | |
| 937 SELECT * FROM t4; | |
| 938 SELECT * FROM t6; | |
| 939 } | |
| 940 } -test { | |
| 941 faultsim_test_result {0 {3 5 7}} | |
| 942 } | |
| 943 | |
| 944 #------------------------------------------------------------------------- | |
| 945 # This tests fault-injection in a special case in the auto-vacuum code. | |
| 946 # | |
| 947 do_test pagerfault-20-pre1 { | |
| 948 faultsim_delete_and_reopen | |
| 949 execsql { | |
| 950 PRAGMA cache_size = 10; | |
| 951 PRAGMA auto_vacuum = FULL; | |
| 952 CREATE TABLE t0(a, b); | |
| 953 } | |
| 954 faultsim_save_and_close | |
| 955 } {} | |
| 956 do_faultsim_test pagerfault-20 -prep { | |
| 957 faultsim_restore_and_reopen | |
| 958 } -body { | |
| 959 execsql { | |
| 960 BEGIN; | |
| 961 CREATE TABLE t1(a, b); | |
| 962 CREATE TABLE t2(a, b); | |
| 963 DROP TABLE t1; | |
| 964 COMMIT; | |
| 965 } | |
| 966 } -test { | |
| 967 faultsim_test_result {0 {}} | |
| 968 } | |
| 969 | |
| 970 do_test pagerfault-21-pre1 { | |
| 971 faultsim_delete_and_reopen | |
| 972 execsql { | |
| 973 PRAGMA cache_size = 10; | |
| 974 CREATE TABLE t0(a PRIMARY KEY, b); | |
| 975 INSERT INTO t0 VALUES(1, 2); | |
| 976 } | |
| 977 faultsim_save_and_close | |
| 978 } {} | |
| 979 do_faultsim_test pagerfault-21 -prep { | |
| 980 faultsim_restore_and_reopen | |
| 981 } -body { | |
| 982 db eval { SELECT * FROM t0 LIMIT 1 } { | |
| 983 db eval { INSERT INTO t0 SELECT a+1, b FROM t0 } | |
| 984 db eval { INSERT INTO t0 SELECT a+2, b FROM t0 } | |
| 985 } | |
| 986 } -test { | |
| 987 faultsim_test_result {0 {}} | |
| 988 } | |
| 989 | |
| 990 | |
| 991 #------------------------------------------------------------------------- | |
| 992 # Test fault-injection and rollback when the nReserve header value | |
| 993 # is non-zero. | |
| 994 # | |
| 995 do_test pagerfault-21-pre1 { | |
| 996 faultsim_delete_and_reopen | |
| 997 execsql { | |
| 998 PRAGMA page_size = 1024; | |
| 999 PRAGMA journal_mode = WAL; | |
| 1000 PRAGMA journal_mode = DELETE; | |
| 1001 } | |
| 1002 db close | |
| 1003 hexio_write test.db 20 10 | |
| 1004 hexio_write test.db 105 03F0 | |
| 1005 sqlite3 db test.db | |
| 1006 db func a_string a_string | |
| 1007 execsql { | |
| 1008 CREATE TABLE t0(a PRIMARY KEY, b UNIQUE); | |
| 1009 INSERT INTO t0 VALUES(a_string(222), a_string(333)); | |
| 1010 INSERT INTO t0 VALUES(a_string(223), a_string(334)); | |
| 1011 INSERT INTO t0 VALUES(a_string(224), a_string(335)); | |
| 1012 INSERT INTO t0 VALUES(a_string(225), a_string(336)); | |
| 1013 } | |
| 1014 faultsim_save_and_close | |
| 1015 } {} | |
| 1016 | |
| 1017 do_faultsim_test pagerfault-21 -prep { | |
| 1018 faultsim_restore_and_reopen | |
| 1019 } -body { | |
| 1020 execsql { INSERT INTO t0 SELECT a||'x', b||'x' FROM t0 } | |
| 1021 } -test { | |
| 1022 faultsim_test_result {0 {}} | |
| 1023 faultsim_integrity_check | |
| 1024 } | |
| 1025 ifcapable crashtest { | |
| 1026 faultsim_delete_and_reopen | |
| 1027 execsql { | |
| 1028 PRAGMA page_size = 1024; | |
| 1029 PRAGMA journal_mode = WAL; | |
| 1030 PRAGMA journal_mode = DELETE; | |
| 1031 } | |
| 1032 db close | |
| 1033 hexio_write test.db 20 10 | |
| 1034 hexio_write test.db 105 03F0 | |
| 1035 | |
| 1036 sqlite3 db test.db | |
| 1037 db func a_string a_string | |
| 1038 execsql { | |
| 1039 CREATE TABLE t0(a PRIMARY KEY, b UNIQUE); | |
| 1040 INSERT INTO t0 VALUES(a_string(222), a_string(333)); | |
| 1041 INSERT INTO t0 VALUES(a_string(223), a_string(334)); | |
| 1042 } | |
| 1043 faultsim_save_and_close | |
| 1044 | |
| 1045 for {set iTest 1} {$iTest<50} {incr iTest} { | |
| 1046 do_test pagerfault-21.crash.$iTest.1 { | |
| 1047 crashsql -delay 1 -file test.db -seed $iTest { | |
| 1048 BEGIN; | |
| 1049 CREATE TABLE t1(a PRIMARY KEY, b UNIQUE); | |
| 1050 INSERT INTO t1 SELECT a, b FROM t0; | |
| 1051 COMMIT; | |
| 1052 } | |
| 1053 } {1 {child process exited abnormally}} | |
| 1054 do_test pagerfault-22.$iTest.2 { | |
| 1055 sqlite3 db test.db | |
| 1056 execsql { PRAGMA integrity_check } | |
| 1057 } {ok} | |
| 1058 db close | |
| 1059 } | |
| 1060 } | |
| 1061 | |
| 1062 | |
| 1063 #------------------------------------------------------------------------- | |
| 1064 # When a 3.7.0 client opens a write-transaction on a database file that | |
| 1065 # has been appended to or truncated by a pre-370 client, it updates | |
| 1066 # the db-size in the file header immediately. This test case provokes | |
| 1067 # errors during that operation. | |
| 1068 # | |
| 1069 do_test pagerfault-22-pre1 { | |
| 1070 faultsim_delete_and_reopen | |
| 1071 db func a_string a_string | |
| 1072 execsql { | |
| 1073 PRAGMA page_size = 1024; | |
| 1074 PRAGMA auto_vacuum = 0; | |
| 1075 CREATE TABLE t1(a); | |
| 1076 CREATE INDEX i1 ON t1(a); | |
| 1077 INSERT INTO t1 VALUES(a_string(3000)); | |
| 1078 CREATE TABLE t2(a); | |
| 1079 INSERT INTO t2 VALUES(1); | |
| 1080 } | |
| 1081 db close | |
| 1082 sql36231 { INSERT INTO t1 VALUES(a_string(3000)) } | |
| 1083 faultsim_save_and_close | |
| 1084 } {} | |
| 1085 do_faultsim_test pagerfault-22 -prep { | |
| 1086 faultsim_restore_and_reopen | |
| 1087 } -body { | |
| 1088 execsql { INSERT INTO t2 VALUES(2) } | |
| 1089 execsql { SELECT * FROM t2 } | |
| 1090 } -test { | |
| 1091 faultsim_test_result {0 {1 2}} | |
| 1092 faultsim_integrity_check | |
| 1093 } | |
| 1094 | |
| 1095 #------------------------------------------------------------------------- | |
| 1096 # Provoke an OOM error during a commit of multi-file transaction. One of | |
| 1097 # the databases written during the transaction is an in-memory database. | |
| 1098 # This test causes rollback of the in-memory database after CommitPhaseOne() | |
| 1099 # has successfully returned. i.e. the series of calls for the aborted commit | |
| 1100 # is: | |
| 1101 # | |
| 1102 # PagerCommitPhaseOne(<in-memory-db>) -> SQLITE_OK | |
| 1103 # PagerCommitPhaseOne(<file-db>) -> SQLITE_IOERR | |
| 1104 # PagerRollback(<in-memory-db>) | |
| 1105 # PagerRollback(<file-db>) | |
| 1106 # | |
| 1107 do_faultsim_test pagerfault-23 -prep { | |
| 1108 sqlite3 db :memory: | |
| 1109 foreach f [glob -nocomplain test.db*] { forcedelete $f } | |
| 1110 db eval { | |
| 1111 ATTACH 'test.db2' AS aux; | |
| 1112 CREATE TABLE t1(a, b); | |
| 1113 CREATE TABLE aux.t2(a, b); | |
| 1114 } | |
| 1115 } -body { | |
| 1116 execsql { | |
| 1117 BEGIN; | |
| 1118 INSERT INTO t1 VALUES(1,2); | |
| 1119 INSERT INTO t2 VALUES(3,4); | |
| 1120 COMMIT; | |
| 1121 } | |
| 1122 } -test { | |
| 1123 faultsim_test_result {0 {}} | |
| 1124 faultsim_integrity_check | |
| 1125 } | |
| 1126 | |
| 1127 do_faultsim_test pagerfault-24 -prep { | |
| 1128 faultsim_delete_and_reopen | |
| 1129 db eval { PRAGMA temp_store = file } | |
| 1130 execsql { CREATE TABLE x(a, b) } | |
| 1131 } -body { | |
| 1132 execsql { CREATE TEMP TABLE t1(a, b) } | |
| 1133 } -test { | |
| 1134 faultsim_test_result {0 {}} \ | |
| 1135 {1 {unable to open a temporary database file for storing temporary tables}} | |
| 1136 set ic [db eval { PRAGMA temp.integrity_check }] | |
| 1137 if {$ic != "ok"} { error "Integrity check: $ic" } | |
| 1138 } | |
| 1139 | |
| 1140 proc lockrows {n} { | |
| 1141 if {$n==0} { return "" } | |
| 1142 db eval { SELECT * FROM t1 WHERE oid = $n } { | |
| 1143 return [lockrows [expr {$n-1}]] | |
| 1144 } | |
| 1145 } | |
| 1146 | |
| 1147 | |
| 1148 do_test pagerfault-25-pre1 { | |
| 1149 faultsim_delete_and_reopen | |
| 1150 db func a_string a_string | |
| 1151 execsql { | |
| 1152 PRAGMA page_size = 1024; | |
| 1153 PRAGMA auto_vacuum = 0; | |
| 1154 CREATE TABLE t1(a); | |
| 1155 INSERT INTO t1 VALUES(a_string(500)); | |
| 1156 INSERT INTO t1 SELECT a_string(500) FROM t1; | |
| 1157 INSERT INTO t1 SELECT a_string(500) FROM t1; | |
| 1158 INSERT INTO t1 SELECT a_string(500) FROM t1; | |
| 1159 INSERT INTO t1 SELECT a_string(500) FROM t1; | |
| 1160 INSERT INTO t1 SELECT a_string(500) FROM t1; | |
| 1161 } | |
| 1162 faultsim_save_and_close | |
| 1163 } {} | |
| 1164 do_faultsim_test pagerfault-25 -prep { | |
| 1165 faultsim_restore_and_reopen | |
| 1166 db func a_string a_string | |
| 1167 set ::channel [db incrblob -readonly t1 a 1] | |
| 1168 execsql { | |
| 1169 PRAGMA cache_size = 10; | |
| 1170 BEGIN; | |
| 1171 INSERT INTO t1 VALUES(a_string(3000)); | |
| 1172 INSERT INTO t1 VALUES(a_string(3000)); | |
| 1173 } | |
| 1174 } -body { | |
| 1175 lockrows 30 | |
| 1176 } -test { | |
| 1177 catch { lockrows 30 } | |
| 1178 catch { db eval COMMIT } | |
| 1179 close $::channel | |
| 1180 faultsim_test_result {0 {}} | |
| 1181 } | |
| 1182 | |
| 1183 do_faultsim_test pagerfault-26 -prep { | |
| 1184 faultsim_delete_and_reopen | |
| 1185 execsql { | |
| 1186 PRAGMA page_size = 1024; | |
| 1187 PRAGMA journal_mode = truncate; | |
| 1188 PRAGMA auto_vacuum = full; | |
| 1189 PRAGMA locking_mode=exclusive; | |
| 1190 CREATE TABLE t1(a, b); | |
| 1191 INSERT INTO t1 VALUES(1, 2); | |
| 1192 PRAGMA page_size = 4096; | |
| 1193 } | |
| 1194 } -body { | |
| 1195 execsql { | |
| 1196 VACUUM; | |
| 1197 } | |
| 1198 } -test { | |
| 1199 faultsim_test_result {0 {}} | |
| 1200 | |
| 1201 set contents [db eval {SELECT * FROM t1}] | |
| 1202 if {$contents != "1 2"} { error "Bad database contents ($contents)" } | |
| 1203 | |
| 1204 set sz [file size test.db] | |
| 1205 if {$testrc!=0 && $sz!=1024*3 && $sz!=4096*3} { | |
| 1206 error "Expected file size to be 3072 or 12288 bytes - actual size $sz bytes" | |
| 1207 } | |
| 1208 if {$testrc==0 && $sz!=4096*3} { | |
| 1209 error "Expected file size to be 12288 bytes - actual size $sz bytes" | |
| 1210 } | |
| 1211 } | |
| 1212 | |
| 1213 do_test pagerfault-27-pre { | |
| 1214 faultsim_delete_and_reopen | |
| 1215 db func a_string a_string | |
| 1216 execsql { | |
| 1217 PRAGMA page_size = 1024; | |
| 1218 CREATE TABLE t1(a, b); | |
| 1219 CREATE TABLE t2(a UNIQUE, b UNIQUE); | |
| 1220 INSERT INTO t2 VALUES( a_string(800), a_string(800) ); | |
| 1221 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1222 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1223 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1224 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1225 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1226 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1227 INSERT INTO t1 VALUES (a_string(20000), a_string(20000)); | |
| 1228 } | |
| 1229 faultsim_save_and_close | |
| 1230 } {} | |
| 1231 do_faultsim_test pagerfault-27 -faults ioerr-persistent -prep { | |
| 1232 faultsim_restore_and_reopen | |
| 1233 db func a_string a_string | |
| 1234 execsql { | |
| 1235 PRAGMA cache_size = 10; | |
| 1236 BEGIN EXCLUSIVE; | |
| 1237 } | |
| 1238 set ::channel [db incrblob t1 a 1] | |
| 1239 } -body { | |
| 1240 puts $::channel [string repeat abc 6000] | |
| 1241 flush $::channel | |
| 1242 } -test { | |
| 1243 catchsql { UPDATE t2 SET a = a_string(800), b = a_string(800) } | |
| 1244 catch { close $::channel } | |
| 1245 catchsql { ROLLBACK } | |
| 1246 faultsim_integrity_check | |
| 1247 } | |
| 1248 | |
| 1249 | |
| 1250 #------------------------------------------------------------------------- | |
| 1251 # | |
| 1252 do_test pagerfault-28-pre { | |
| 1253 faultsim_delete_and_reopen | |
| 1254 db func a_string a_string | |
| 1255 execsql { | |
| 1256 PRAGMA page_size = 512; | |
| 1257 | |
| 1258 PRAGMA journal_mode = wal; | |
| 1259 PRAGMA wal_autocheckpoint = 0; | |
| 1260 PRAGMA cache_size = 100000; | |
| 1261 | |
| 1262 BEGIN; | |
| 1263 CREATE TABLE t2(a UNIQUE, b UNIQUE); | |
| 1264 INSERT INTO t2 VALUES( a_string(800), a_string(800) ); | |
| 1265 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1266 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1267 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1268 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1269 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1270 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1271 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1272 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1273 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1274 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1275 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1276 COMMIT; | |
| 1277 CREATE TABLE t1(a PRIMARY KEY, b); | |
| 1278 } | |
| 1279 expr {[file size test.db-shm] >= 96*1024} | |
| 1280 } {1} | |
| 1281 faultsim_save_and_close | |
| 1282 | |
| 1283 do_faultsim_test pagerfault-28a -faults oom* -prep { | |
| 1284 faultsim_restore_and_reopen | |
| 1285 execsql { PRAGMA mmap_size=0 } | |
| 1286 | |
| 1287 sqlite3 db2 test.db | |
| 1288 db2 eval { SELECT count(*) FROM t2 } | |
| 1289 | |
| 1290 db func a_string a_string | |
| 1291 execsql { | |
| 1292 BEGIN; | |
| 1293 INSERT INTO t1 VALUES(a_string(2000), a_string(2000)); | |
| 1294 INSERT INTO t1 VALUES(a_string(2000), a_string(2000)); | |
| 1295 } | |
| 1296 set ::STMT [sqlite3_prepare db "SELECT * FROM t1 ORDER BY a" -1 DUMMY] | |
| 1297 sqlite3_step $::STMT | |
| 1298 } -body { | |
| 1299 execsql { ROLLBACK } | |
| 1300 } -test { | |
| 1301 db2 close | |
| 1302 sqlite3_finalize $::STMT | |
| 1303 catchsql { ROLLBACK } | |
| 1304 faultsim_integrity_check | |
| 1305 } | |
| 1306 | |
| 1307 faultsim_restore_and_reopen | |
| 1308 sqlite3 db2 test.db | |
| 1309 db2 eval {SELECT count(*) FROM t2} | |
| 1310 db close | |
| 1311 | |
| 1312 do_faultsim_test pagerfault-28b -faults oom* -prep { | |
| 1313 sqlite3 db test.db | |
| 1314 } -body { | |
| 1315 execsql { SELECT count(*) FROM t2 } | |
| 1316 } -test { | |
| 1317 faultsim_test_result {0 2048} | |
| 1318 db close | |
| 1319 } | |
| 1320 | |
| 1321 db2 close | |
| 1322 | |
| 1323 #------------------------------------------------------------------------- | |
| 1324 # Try this: | |
| 1325 # | |
| 1326 # 1) Put the pager in ERROR state (error during rollback) | |
| 1327 # | |
| 1328 # 2) Next time the connection is used inject errors into all xWrite() and | |
| 1329 # xUnlock() calls. This causes the hot-journal rollback to fail and | |
| 1330 # the pager to declare its locking state UNKNOWN. | |
| 1331 # | |
| 1332 # 3) Same again. | |
| 1333 # | |
| 1334 # 4a) Stop injecting errors. Allow the rollback to succeed. Check that | |
| 1335 # the database is Ok. Or, | |
| 1336 # | |
| 1337 # 4b) Close and reopen the db. Check that the db is Ok. | |
| 1338 # | |
| 1339 proc custom_injectinstall {} { | |
| 1340 testvfs custom -default true | |
| 1341 custom filter {xWrite xUnlock} | |
| 1342 } | |
| 1343 proc custom_injectuninstall {} { | |
| 1344 catch {db close} | |
| 1345 catch {db2 close} | |
| 1346 custom delete | |
| 1347 } | |
| 1348 proc custom_injectstart {iFail} { | |
| 1349 custom ioerr $iFail 1 | |
| 1350 } | |
| 1351 proc custom_injectstop {} { | |
| 1352 custom ioerr | |
| 1353 } | |
| 1354 set ::FAULTSIM(custom) [list \ | |
| 1355 -injectinstall custom_injectinstall \ | |
| 1356 -injectstart custom_injectstart \ | |
| 1357 -injectstop custom_injectstop \ | |
| 1358 -injecterrlist {{1 {disk I/O error}}} \ | |
| 1359 -injectuninstall custom_injectuninstall \ | |
| 1360 ] | |
| 1361 | |
| 1362 do_test pagerfault-29-pre { | |
| 1363 faultsim_delete_and_reopen | |
| 1364 db func a_string a_string | |
| 1365 execsql { | |
| 1366 PRAGMA page_size = 1024; | |
| 1367 PRAGMA cache_size = 5; | |
| 1368 | |
| 1369 BEGIN; | |
| 1370 CREATE TABLE t2(a UNIQUE, b UNIQUE); | |
| 1371 INSERT INTO t2 VALUES( a_string(800), a_string(800) ); | |
| 1372 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1373 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1374 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1375 INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; | |
| 1376 COMMIT; | |
| 1377 } | |
| 1378 expr {[file size test.db] >= 50*1024} | |
| 1379 } {1} | |
| 1380 faultsim_save_and_close | |
| 1381 foreach {tn tt} { | |
| 1382 29 { catchsql ROLLBACK } | |
| 1383 30 { db close ; sqlite3 db test.db } | |
| 1384 } { | |
| 1385 do_faultsim_test pagerfault-$tn -faults custom -prep { | |
| 1386 faultsim_restore_and_reopen | |
| 1387 db func a_string a_string | |
| 1388 execsql { | |
| 1389 PRAGMA cache_size = 5; | |
| 1390 BEGIN; | |
| 1391 UPDATE t2 SET a = a_string(799); | |
| 1392 } | |
| 1393 } -body { | |
| 1394 catchsql ROLLBACK | |
| 1395 catchsql ROLLBACK | |
| 1396 catchsql ROLLBACK | |
| 1397 } -test { | |
| 1398 eval $::tt | |
| 1399 if {"ok" != [db one {PRAGMA integrity_check}]} { | |
| 1400 error "integrity check failed" | |
| 1401 } | |
| 1402 } | |
| 1403 } | |
| 1404 | |
| 1405 do_test pagerfault-31-pre { | |
| 1406 sqlite3_shutdown | |
| 1407 sqlite3_config_uri 1 | |
| 1408 } {SQLITE_OK} | |
| 1409 do_faultsim_test pagerfault-31 -faults oom* -body { | |
| 1410 sqlite3 db {file:one?mode=memory&cache=shared} | |
| 1411 db eval { | |
| 1412 CREATE TABLE t1(x); | |
| 1413 INSERT INTO t1 VALUES(1); | |
| 1414 SELECT * FROM t1; | |
| 1415 } | |
| 1416 } -test { | |
| 1417 faultsim_test_result {0 1} {1 {}} | |
| 1418 catch { db close } | |
| 1419 } | |
| 1420 sqlite3_shutdown | |
| 1421 sqlite3_config_uri 0 | |
| 1422 | |
| 1423 do_test pagerfault-32-pre { | |
| 1424 reset_db | |
| 1425 execsql { | |
| 1426 CREATE TABLE t1(x); | |
| 1427 INSERT INTO t1 VALUES('one'); | |
| 1428 } | |
| 1429 } {} | |
| 1430 faultsim_save_and_close | |
| 1431 | |
| 1432 do_faultsim_test pagerfault-32 -prep { | |
| 1433 faultsim_restore_and_reopen | |
| 1434 db eval { SELECT * FROM t1; } | |
| 1435 } -body { | |
| 1436 execsql { SELECT * FROM t1; } | |
| 1437 } -test { | |
| 1438 faultsim_test_result {0 one} | |
| 1439 } | |
| 1440 sqlite3_shutdown | |
| 1441 sqlite3_config_uri 0 | |
| 1442 | |
| 1443 do_faultsim_test pagerfault-33a -prep { | |
| 1444 sqlite3 db :memory: | |
| 1445 execsql { | |
| 1446 CREATE TABLE t1(a, b); | |
| 1447 INSERT INTO t1 VALUES(1, 2); | |
| 1448 } | |
| 1449 } -body { | |
| 1450 execsql { VACUUM } | |
| 1451 } -test { | |
| 1452 faultsim_test_result {0 {}} | |
| 1453 } | |
| 1454 do_faultsim_test pagerfault-33b -prep { | |
| 1455 sqlite3 db "" | |
| 1456 execsql { | |
| 1457 CREATE TABLE t1(a, b); | |
| 1458 INSERT INTO t1 VALUES(1, 2); | |
| 1459 } | |
| 1460 } -body { | |
| 1461 execsql { VACUUM } | |
| 1462 } -test { | |
| 1463 faultsim_test_result {0 {}} | |
| 1464 } | |
| 1465 | |
| 1466 do_test pagerfault-34-pre { | |
| 1467 reset_db | |
| 1468 execsql { | |
| 1469 CREATE TABLE t1(x PRIMARY KEY); | |
| 1470 } | |
| 1471 } {} | |
| 1472 faultsim_save_and_close | |
| 1473 do_faultsim_test pagerfault-34 -prep { | |
| 1474 faultsim_restore_and_reopen | |
| 1475 execsql { | |
| 1476 BEGIN; | |
| 1477 INSERT INTO t1 VALUES( randomblob(4000) ); | |
| 1478 DELETE FROM t1; | |
| 1479 } | |
| 1480 } -body { | |
| 1481 execsql COMMIT | |
| 1482 } -test { | |
| 1483 faultsim_test_result {0 {}} | |
| 1484 } | |
| 1485 | |
| 1486 do_test pagerfault-35-pre { | |
| 1487 faultsim_delete_and_reopen | |
| 1488 execsql { | |
| 1489 CREATE TABLE t1(x PRIMARY KEY, y); | |
| 1490 INSERT INTO t1 VALUES(randomblob(200), randomblob(200)); | |
| 1491 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 1492 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 1493 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 1494 } | |
| 1495 faultsim_save_and_close | |
| 1496 } {} | |
| 1497 testvfs tv -default 1 | |
| 1498 tv sectorsize 8192; | |
| 1499 tv devchar [list] | |
| 1500 do_faultsim_test pagerfault-35 -prep { | |
| 1501 faultsim_restore_and_reopen | |
| 1502 } -body { | |
| 1503 execsql { UPDATE t1 SET x=randomblob(200) } | |
| 1504 } -test { | |
| 1505 faultsim_test_result {0 {}} | |
| 1506 } | |
| 1507 catch {db close} | |
| 1508 tv delete | |
| 1509 | |
| 1510 sqlite3_shutdown | |
| 1511 sqlite3_config_uri 1 | |
| 1512 do_test pagerfault-36-pre { | |
| 1513 faultsim_delete_and_reopen | |
| 1514 execsql { | |
| 1515 CREATE TABLE t1(x PRIMARY KEY, y); | |
| 1516 INSERT INTO t1 VALUES(randomblob(200), randomblob(200)); | |
| 1517 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 1518 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 1519 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 1520 } | |
| 1521 faultsim_save_and_close | |
| 1522 } {} | |
| 1523 do_faultsim_test pagerfault-36 -prep { | |
| 1524 faultsim_restore | |
| 1525 sqlite3 db file:test.db?cache=shared | |
| 1526 sqlite3 db2 file:test.db?cache=shared | |
| 1527 db2 eval { | |
| 1528 BEGIN; | |
| 1529 SELECT count(*) FROM sqlite_master; | |
| 1530 } | |
| 1531 db eval { | |
| 1532 PRAGMA cache_size = 1; | |
| 1533 BEGIN; | |
| 1534 UPDATE t1 SET x = randomblob(200); | |
| 1535 } | |
| 1536 } -body { | |
| 1537 execsql ROLLBACK db | |
| 1538 } -test { | |
| 1539 catch { db eval {UPDATE t1 SET x = randomblob(200)} } | |
| 1540 faultsim_test_result {0 {}} | |
| 1541 catch { db close } | |
| 1542 catch { db2 close } | |
| 1543 } | |
| 1544 | |
| 1545 sqlite3_shutdown | |
| 1546 sqlite3_config_uri 0 | |
| 1547 sqlite3_initialize | |
| 1548 | |
| 1549 finish_test | |
| OLD | NEW |