OLD | NEW |
| (Empty) |
1 # 2005 December 30 | |
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 # The focus of the tests in this file are IO errors that occur in a shared | |
13 # cache context. What happens to connection B if one connection A encounters | |
14 # an IO-error whilst reading or writing the file-system? | |
15 # | |
16 # $Id: shared_err.test,v 1.24 2008/10/12 00:27:54 shane Exp $ | |
17 | |
18 proc skip {args} {} | |
19 | |
20 | |
21 set testdir [file dirname $argv0] | |
22 source $testdir/tester.tcl | |
23 source $testdir/malloc_common.tcl | |
24 db close | |
25 | |
26 ifcapable !shared_cache||!subquery { | |
27 finish_test | |
28 return | |
29 } | |
30 | |
31 set ::enable_shared_cache [sqlite3_enable_shared_cache 1] | |
32 | |
33 do_ioerr_test shared_ioerr-1 -tclprep { | |
34 sqlite3 db2 test.db | |
35 execsql { | |
36 PRAGMA read_uncommitted = 1; | |
37 CREATE TABLE t1(a,b,c); | |
38 BEGIN; | |
39 SELECT * FROM sqlite_master; | |
40 } db2 | |
41 } -sqlbody { | |
42 SELECT * FROM sqlite_master; | |
43 INSERT INTO t1 VALUES(1,2,3); | |
44 BEGIN TRANSACTION; | |
45 INSERT INTO t1 VALUES(1,2,3); | |
46 INSERT INTO t1 VALUES(4,5,6); | |
47 ROLLBACK; | |
48 SELECT * FROM t1; | |
49 BEGIN TRANSACTION; | |
50 INSERT INTO t1 VALUES(1,2,3); | |
51 INSERT INTO t1 VALUES(4,5,6); | |
52 COMMIT; | |
53 SELECT * FROM t1; | |
54 DELETE FROM t1 WHERE a<100; | |
55 } -cleanup { | |
56 do_test shared_ioerr-1.$n.cleanup.1 { | |
57 set res [catchsql { | |
58 SELECT * FROM t1; | |
59 } db2] | |
60 set possible_results [list \ | |
61 "1 {disk I/O error}" \ | |
62 "0 {1 2 3}" \ | |
63 "0 {1 2 3 1 2 3 4 5 6}" \ | |
64 "0 {1 2 3 1 2 3 4 5 6 1 2 3 4 5 6}" \ | |
65 "0 {}" \ | |
66 "1 {database disk image is malformed}" \ | |
67 ] | |
68 set rc [expr [lsearch -exact $possible_results $res] >= 0] | |
69 if {$rc != 1} { | |
70 puts "" | |
71 puts "Result: $res" | |
72 } | |
73 set rc | |
74 } {1} | |
75 | |
76 # The "database disk image is malformed" is a special case that can | |
77 # occur if an IO error occurs during a rollback in the {SELECT * FROM t1} | |
78 # statement above. This test is to make sure there is no real database | |
79 # corruption. | |
80 db2 close | |
81 do_test shared_ioerr-1.$n.cleanup.2 { | |
82 execsql {pragma integrity_check} db | |
83 } {ok} | |
84 } | |
85 | |
86 do_ioerr_test shared_ioerr-2 -tclprep { | |
87 sqlite3 db2 test.db | |
88 execsql { | |
89 PRAGMA read_uncommitted = 1; | |
90 BEGIN; | |
91 CREATE TABLE t1(a, b); | |
92 INSERT INTO t1(oid) VALUES(NULL); | |
93 INSERT INTO t1(oid) SELECT NULL FROM t1; | |
94 INSERT INTO t1(oid) SELECT NULL FROM t1; | |
95 INSERT INTO t1(oid) SELECT NULL FROM t1; | |
96 INSERT INTO t1(oid) SELECT NULL FROM t1; | |
97 INSERT INTO t1(oid) SELECT NULL FROM t1; | |
98 INSERT INTO t1(oid) SELECT NULL FROM t1; | |
99 INSERT INTO t1(oid) SELECT NULL FROM t1; | |
100 INSERT INTO t1(oid) SELECT NULL FROM t1; | |
101 INSERT INTO t1(oid) SELECT NULL FROM t1; | |
102 INSERT INTO t1(oid) SELECT NULL FROM t1; | |
103 UPDATE t1 set a = oid, b = 'abcdefghijklmnopqrstuvwxyz0123456789'; | |
104 CREATE INDEX i1 ON t1(a); | |
105 COMMIT; | |
106 BEGIN; | |
107 SELECT * FROM sqlite_master; | |
108 } db2 | |
109 } -tclbody { | |
110 set ::residx 0 | |
111 execsql {DELETE FROM t1 WHERE 0 = (a % 2);} | |
112 incr ::residx | |
113 | |
114 # When this transaction begins the table contains 512 entries. The | |
115 # two statements together add 512+146 more if it succeeds. | |
116 # (1024/7==146) | |
117 execsql {BEGIN;} | |
118 execsql {INSERT INTO t1 SELECT a+1, b FROM t1;} | |
119 execsql {INSERT INTO t1 SELECT 'string' || a, b FROM t1 WHERE 0 = (a%7);} | |
120 execsql {COMMIT;} | |
121 | |
122 incr ::residx | |
123 } -cleanup { | |
124 catchsql ROLLBACK | |
125 do_test shared_ioerr-2.$n.cleanup.1 { | |
126 set res [catchsql { | |
127 SELECT max(a), min(a), count(*) FROM (SELECT a FROM t1 order by a); | |
128 } db2] | |
129 set possible_results [list \ | |
130 {0 {1024 1 1024}} \ | |
131 {0 {1023 1 512}} \ | |
132 {0 {string994 1 1170}} \ | |
133 ] | |
134 set idx [lsearch -exact $possible_results $res] | |
135 set success [expr {$idx==$::residx || $res=="1 {disk I/O error}"}] | |
136 if {!$success} { | |
137 puts "" | |
138 puts "Result: \"$res\" ($::residx)" | |
139 } | |
140 set success | |
141 } {1} | |
142 db2 close | |
143 } | |
144 | |
145 # This test is designed to provoke an IO error when a cursor position is | |
146 # "saved" (because another cursor is going to modify the underlying table). | |
147 # | |
148 do_ioerr_test shared_ioerr-3 -tclprep { | |
149 sqlite3 db2 test.db | |
150 execsql { | |
151 PRAGMA read_uncommitted = 1; | |
152 PRAGMA cache_size = 10; | |
153 BEGIN; | |
154 CREATE TABLE t1(a, b, UNIQUE(a, b)); | |
155 } db2 | |
156 for {set i 0} {$i < 200} {incr i} { | |
157 set a [string range [string repeat "[format %03d $i]." 5] 0 end-1] | |
158 | |
159 set b [string repeat $i 2000] | |
160 execsql {INSERT INTO t1 VALUES($a, $b)} db2 | |
161 } | |
162 execsql {COMMIT} db2 | |
163 set ::DB2 [sqlite3_connection_pointer db2] | |
164 set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY] | |
165 sqlite3_step $::STMT ;# Cursor points at 000.000.000.000 | |
166 sqlite3_step $::STMT ;# Cursor points at 001.001.001.001 | |
167 | |
168 } -tclbody { | |
169 execsql { | |
170 BEGIN; | |
171 INSERT INTO t1 VALUES('201.201.201.201.201', NULL); | |
172 UPDATE t1 SET a = '202.202.202.202.202' WHERE a LIKE '201%'; | |
173 COMMIT; | |
174 } | |
175 } -cleanup { | |
176 set ::steprc [sqlite3_step $::STMT] | |
177 set ::column [sqlite3_column_text $::STMT 0] | |
178 set ::finalrc [sqlite3_finalize $::STMT] | |
179 | |
180 # There are three possible outcomes here (assuming persistent IO errors): | |
181 # | |
182 # 1. If the [sqlite3_step] did not require any IO (required pages in | |
183 # the cache), then the next row ("002...") may be retrieved | |
184 # successfully. | |
185 # | |
186 # 2. If the [sqlite3_step] does require IO, then [sqlite3_step] returns | |
187 # SQLITE_ERROR and [sqlite3_finalize] returns IOERR. | |
188 # | |
189 # 3. If, after the initial IO error, SQLite tried to rollback the | |
190 # active transaction and a second IO error was encountered, then | |
191 # statement $::STMT will have been aborted. This means [sqlite3_stmt] | |
192 # returns SQLITE_ABORT, and the statement cursor does not move. i.e. | |
193 # [sqlite3_column] still returns the current row ("001...") and | |
194 # [sqlite3_finalize] returns SQLITE_OK. | |
195 # | |
196 | |
197 do_test shared_ioerr-3.$n.cleanup.1 { | |
198 expr { | |
199 $::steprc eq "SQLITE_ROW" || | |
200 $::steprc eq "SQLITE_ERROR" || | |
201 $::steprc eq "SQLITE_ABORT" | |
202 } | |
203 } {1} | |
204 do_test shared_ioerr-3.$n.cleanup.2 { | |
205 expr { | |
206 ($::steprc eq "SQLITE_ROW" && $::column eq "002.002.002.002.002") || | |
207 ($::steprc eq "SQLITE_ERROR" && $::column eq "") || | |
208 ($::steprc eq "SQLITE_ABORT" && $::column eq "001.001.001.001.001") | |
209 } | |
210 } {1} | |
211 do_test shared_ioerr-3.$n.cleanup.3 { | |
212 expr { | |
213 ($::steprc eq "SQLITE_ROW" && $::finalrc eq "SQLITE_OK") || | |
214 ($::steprc eq "SQLITE_ERROR" && $::finalrc eq "SQLITE_IOERR") || | |
215 ($::steprc eq "SQLITE_ERROR" && $::finalrc eq "SQLITE_ABORT") | |
216 } | |
217 } {1} | |
218 | |
219 # db2 eval {select * from sqlite_master} | |
220 db2 close | |
221 } | |
222 | |
223 # This is a repeat of the previous test except that this time we | |
224 # are doing a reverse-order scan of the table when the cursor is | |
225 # "saved". | |
226 # | |
227 do_ioerr_test shared_ioerr-3rev -tclprep { | |
228 sqlite3 db2 test.db | |
229 execsql { | |
230 PRAGMA read_uncommitted = 1; | |
231 PRAGMA cache_size = 10; | |
232 BEGIN; | |
233 CREATE TABLE t1(a, b, UNIQUE(a, b)); | |
234 } db2 | |
235 for {set i 0} {$i < 200} {incr i} { | |
236 set a [string range [string repeat "[format %03d $i]." 5] 0 end-1] | |
237 | |
238 set b [string repeat $i 2000] | |
239 execsql {INSERT INTO t1 VALUES($a, $b)} db2 | |
240 } | |
241 execsql {COMMIT} db2 | |
242 set ::DB2 [sqlite3_connection_pointer db2] | |
243 set ::STMT [sqlite3_prepare $::DB2 \ | |
244 "SELECT a FROM t1 ORDER BY a DESC" -1 DUMMY] | |
245 sqlite3_step $::STMT ;# Cursor points at 199.199.199.199.199 | |
246 sqlite3_step $::STMT ;# Cursor points at 198.198.198.198.198 | |
247 | |
248 } -tclbody { | |
249 execsql { | |
250 BEGIN; | |
251 INSERT INTO t1 VALUES('201.201.201.201.201', NULL); | |
252 UPDATE t1 SET a = '202.202.202.202.202' WHERE a LIKE '201%'; | |
253 COMMIT; | |
254 } | |
255 } -cleanup { | |
256 set ::steprc [sqlite3_step $::STMT] | |
257 set ::column [sqlite3_column_text $::STMT 0] | |
258 set ::finalrc [sqlite3_finalize $::STMT] | |
259 | |
260 # There are three possible outcomes here (assuming persistent IO errors): | |
261 # | |
262 # 1. If the [sqlite3_step] did not require any IO (required pages in | |
263 # the cache), then the next row ("002...") may be retrieved | |
264 # successfully. | |
265 # | |
266 # 2. If the [sqlite3_step] does require IO, then [sqlite3_step] returns | |
267 # SQLITE_ERROR and [sqlite3_finalize] returns IOERR. | |
268 # | |
269 # 3. If, after the initial IO error, SQLite tried to rollback the | |
270 # active transaction and a second IO error was encountered, then | |
271 # statement $::STMT will have been aborted. This means [sqlite3_stmt] | |
272 # returns SQLITE_ABORT, and the statement cursor does not move. i.e. | |
273 # [sqlite3_column] still returns the current row ("001...") and | |
274 # [sqlite3_finalize] returns SQLITE_OK. | |
275 # | |
276 | |
277 do_test shared_ioerr-3rev.$n.cleanup.1 { | |
278 expr { | |
279 $::steprc eq "SQLITE_ROW" || | |
280 $::steprc eq "SQLITE_ERROR" || | |
281 $::steprc eq "SQLITE_ABORT" | |
282 } | |
283 } {1} | |
284 do_test shared_ioerr-3rev.$n.cleanup.2 { | |
285 expr { | |
286 ($::steprc eq "SQLITE_ROW" && $::column eq "197.197.197.197.197") || | |
287 ($::steprc eq "SQLITE_ERROR" && $::column eq "") || | |
288 ($::steprc eq "SQLITE_ABORT" && $::column eq "198.198.198.198.198") | |
289 } | |
290 } {1} | |
291 do_test shared_ioerr-3rev.$n.cleanup.3 { | |
292 expr { | |
293 ($::steprc eq "SQLITE_ROW" && $::finalrc eq "SQLITE_OK") || | |
294 ($::steprc eq "SQLITE_ERROR" && $::finalrc eq "SQLITE_IOERR") || | |
295 ($::steprc eq "SQLITE_ERROR" && $::finalrc eq "SQLITE_ABORT") | |
296 } | |
297 } {1} | |
298 | |
299 # db2 eval {select * from sqlite_master} | |
300 db2 close | |
301 } | |
302 | |
303 # Provoke a malloc() failure when a cursor position is being saved. This | |
304 # only happens with index cursors (because they malloc() space to save the | |
305 # current key value). It does not happen with tables, because an integer | |
306 # key does not require a malloc() to store. | |
307 # | |
308 # The library should return an SQLITE_NOMEM to the caller. The query that | |
309 # owns the cursor (the one for which the position is not saved) should | |
310 # continue unaffected. | |
311 # | |
312 do_malloc_test shared_err-4 -tclprep { | |
313 sqlite3 db2 test.db | |
314 execsql { | |
315 PRAGMA read_uncommitted = 1; | |
316 BEGIN; | |
317 CREATE TABLE t1(a, b, UNIQUE(a, b)); | |
318 } db2 | |
319 for {set i 0} {$i < 5} {incr i} { | |
320 set a [string repeat $i 10] | |
321 set b [string repeat $i 2000] | |
322 execsql {INSERT INTO t1 VALUES($a, $b)} db2 | |
323 } | |
324 execsql {COMMIT} db2 | |
325 set ::DB2 [sqlite3_connection_pointer db2] | |
326 set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY] | |
327 sqlite3_step $::STMT ;# Cursor points at 0000000000 | |
328 sqlite3_step $::STMT ;# Cursor points at 1111111111 | |
329 } -tclbody { | |
330 execsql { | |
331 INSERT INTO t1 VALUES(6, NULL); | |
332 } | |
333 } -cleanup { | |
334 do_test shared_malloc-4.$::n.cleanup.1 { | |
335 set ::rc [sqlite3_step $::STMT] | |
336 expr {$::rc=="SQLITE_ROW" || $::rc=="SQLITE_ERROR"} | |
337 } {1} | |
338 if {$::rc=="SQLITE_ROW"} { | |
339 do_test shared_malloc-4.$::n.cleanup.2 { | |
340 sqlite3_column_text $::STMT 0 | |
341 } {2222222222} | |
342 } | |
343 do_test shared_malloc-4.$::n.cleanup.3 { | |
344 set rc [sqlite3_finalize $::STMT] | |
345 expr {$rc=="SQLITE_OK" || $rc=="SQLITE_ABORT" || | |
346 $rc=="SQLITE_NOMEM" || $rc=="SQLITE_IOERR"} | |
347 } {1} | |
348 # db2 eval {select * from sqlite_master} | |
349 db2 close | |
350 } | |
351 | |
352 do_malloc_test shared_err-5 -tclbody { | |
353 db close | |
354 sqlite3 dbX test.db | |
355 sqlite3 dbY test.db | |
356 dbX close | |
357 dbY close | |
358 } -cleanup { | |
359 catch {dbX close} | |
360 catch {dbY close} | |
361 } | |
362 | |
363 do_malloc_test shared_err-6 -tclbody { | |
364 catch {db close} | |
365 ifcapable deprecated { | |
366 sqlite3_thread_cleanup | |
367 } | |
368 sqlite3_enable_shared_cache 0 | |
369 } -cleanup { | |
370 sqlite3_enable_shared_cache 1 | |
371 } | |
372 | |
373 # As of 3.5.0, sqlite3_enable_shared_cache can be called at | |
374 # any time and from any thread | |
375 #do_test shared_err-misuse-7.1 { | |
376 # sqlite3 db test.db | |
377 # catch { | |
378 # sqlite3_enable_shared_cache 0 | |
379 # } msg | |
380 # set msg | |
381 #} {library routine called out of sequence} | |
382 | |
383 # Again provoke a malloc() failure when a cursor position is being saved, | |
384 # this time during a ROLLBACK operation by some other handle. | |
385 # | |
386 # The library should return an SQLITE_NOMEM to the caller. The query that | |
387 # owns the cursor (the one for which the position is not saved) should | |
388 # be aborted. | |
389 # | |
390 set ::aborted 0 | |
391 do_malloc_test shared_err-8 -tclprep { | |
392 sqlite3 db2 test.db | |
393 execsql { | |
394 PRAGMA read_uncommitted = 1; | |
395 BEGIN; | |
396 CREATE TABLE t1(a, b, UNIQUE(a, b)); | |
397 } db2 | |
398 for {set i 0} {$i < 2} {incr i} { | |
399 set a [string repeat $i 10] | |
400 set b [string repeat $i 2000] | |
401 execsql {INSERT INTO t1 VALUES($a, $b)} db2 | |
402 } | |
403 execsql {COMMIT} db2 | |
404 execsql BEGIN | |
405 execsql ROLLBACK | |
406 set ::DB2 [sqlite3_connection_pointer db2] | |
407 set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY] | |
408 sqlite3_step $::STMT ;# Cursor points at 0000000000 | |
409 sqlite3_step $::STMT ;# Cursor points at 1111111111 | |
410 } -tclbody { | |
411 execsql { | |
412 BEGIN; | |
413 INSERT INTO t1 VALUES(6, NULL); | |
414 ROLLBACK} | |
415 } -cleanup { | |
416 # UPDATE: As of [5668], if the rollback fails SQLITE_CORRUPT is returned. | |
417 # So these tests have been updated to expect SQLITE_CORRUPT and its | |
418 # associated English language error message. | |
419 # | |
420 do_test shared_malloc-8.$::n.cleanup.1 { | |
421 set res [catchsql {SELECT a FROM t1} db2] | |
422 set ans [lindex $res 1] | |
423 if {[lindex $res 0]} { | |
424 set r [expr { | |
425 $ans=="disk I/O error" || | |
426 $ans=="out of memory" || | |
427 $ans=="database disk image is malformed" | |
428 }] | |
429 } else { | |
430 set r [expr {[lrange $ans 0 1]=="0000000000 1111111111"}] | |
431 } | |
432 } {1} | |
433 do_test shared_malloc-8.$::n.cleanup.2 { | |
434 set rc1 [sqlite3_step $::STMT] | |
435 set rc2 [sqlite3_finalize $::STMT] | |
436 if {$rc2=="SQLITE_ABORT"} { | |
437 incr ::aborted | |
438 } | |
439 expr { | |
440 ($rc1=="SQLITE_DONE" && $rc2=="SQLITE_OK") || | |
441 ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_ABORT") || | |
442 ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_NOMEM") || | |
443 ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_IOERR") || | |
444 ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_CORRUPT") | |
445 } | |
446 } {1} | |
447 db2 close | |
448 } | |
449 | |
450 # When this test case was written, OOM errors in write statements would | |
451 # cause transaction rollback, which would trip cursors in other statements, | |
452 # aborting them. This no longer happens. | |
453 # | |
454 do_test shared_malloc-8.X { | |
455 # Test that one or more queries were aborted due to the malloc() failure. | |
456 # expr $::aborted>=1 | |
457 expr $::aborted==0 | |
458 } {1} | |
459 | |
460 # This test is designed to catch a specific bug that was present during | |
461 # development of 3.5.0. If a malloc() failed while setting the page-size, | |
462 # a buffer (Pager.pTmpSpace) was being freed. This could cause a seg-fault | |
463 # later if another connection tried to use the pager. | |
464 # | |
465 # This test will crash 3.4.2. | |
466 # | |
467 do_malloc_test shared_err-9 -tclprep { | |
468 sqlite3 db2 test.db | |
469 } -sqlbody { | |
470 PRAGMA page_size = 4096; | |
471 PRAGMA page_size = 1024; | |
472 } -cleanup { | |
473 db2 eval { | |
474 CREATE TABLE abc(a, b, c); | |
475 BEGIN; | |
476 INSERT INTO abc VALUES(1, 2, 3); | |
477 ROLLBACK; | |
478 } | |
479 db2 close | |
480 } | |
481 | |
482 catch {db close} | |
483 catch {db2 close} | |
484 do_malloc_test shared_err-10 -tclprep { | |
485 sqlite3 db test.db | |
486 sqlite3 db2 test.db | |
487 | |
488 db eval { SELECT * FROM sqlite_master } | |
489 db2 eval { | |
490 BEGIN; | |
491 CREATE TABLE abc(a, b, c); | |
492 } | |
493 } -tclbody { | |
494 catch {db eval {SELECT * FROM sqlite_master}} | |
495 error 1 | |
496 } -cleanup { | |
497 execsql { SELECT * FROM sqlite_master } | |
498 } | |
499 | |
500 do_malloc_test shared_err-11 -tclprep { | |
501 sqlite3 db test.db | |
502 sqlite3 db2 test.db | |
503 | |
504 db eval { SELECT * FROM sqlite_master } | |
505 db2 eval { | |
506 BEGIN; | |
507 CREATE TABLE abc(a, b, c); | |
508 } | |
509 } -tclbody { | |
510 catch {db eval {SELECT * FROM sqlite_master}} | |
511 catch {sqlite3_errmsg16 db} | |
512 error 1 | |
513 } -cleanup { | |
514 execsql { SELECT * FROM sqlite_master } | |
515 } | |
516 | |
517 catch {db close} | |
518 catch {db2 close} | |
519 | |
520 do_malloc_test shared_err-12 -sqlbody { | |
521 CREATE TABLE abc(a, b, c); | |
522 INSERT INTO abc VALUES(1, 2, 3); | |
523 } | |
524 | |
525 catch {db close} | |
526 catch {db2 close} | |
527 sqlite3_enable_shared_cache $::enable_shared_cache | |
528 finish_test | |
OLD | NEW |