blob: cdbc98a21fc4d8e719c1391e20829ba76b4f87b9 [file] [log] [blame]
danielk197707cb5602006-01-20 10:55:05 +00001# 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#
danielk197797a227c2006-01-20 16:32:04 +000016# $Id: shared_err.test,v 1.2 2006/01/20 16:32:05 danielk1977 Exp $
danielk197707cb5602006-01-20 10:55:05 +000017
18proc skip {args} {}
19
20
21set testdir [file dirname $argv0]
22source $testdir/tester.tcl
23db close
24
25ifcapable !shared_cache||!subquery {
26 finish_test
27 return
28}
29set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
30
danielk197707cb5602006-01-20 10:55:05 +000031do_ioerr_test shared_ioerr-1 -tclprep {
32 sqlite3 db2 test.db
33 execsql {
34 PRAGMA read_uncommitted = 1;
35 CREATE TABLE t1(a,b,c);
36 BEGIN;
37 SELECT * FROM sqlite_master;
38 } db2
39} -sqlbody {
40 SELECT * FROM sqlite_master;
41 INSERT INTO t1 VALUES(1,2,3);
42 BEGIN TRANSACTION;
43 INSERT INTO t1 VALUES(1,2,3);
44 INSERT INTO t1 VALUES(4,5,6);
45 ROLLBACK;
46 SELECT * FROM t1;
47 BEGIN TRANSACTION;
48 INSERT INTO t1 VALUES(1,2,3);
49 INSERT INTO t1 VALUES(4,5,6);
50 COMMIT;
51 SELECT * FROM t1;
52 DELETE FROM t1 WHERE a<100;
53} -cleanup {
danielk197797a227c2006-01-20 16:32:04 +000054 do_test shared_ioerr-1.$n.cleanup.1 {
danielk197707cb5602006-01-20 10:55:05 +000055 set res [catchsql {
56 SELECT * FROM t1;
57 } db2]
58 set possible_results [list \
59 "1 {disk I/O error}" \
60 "0 {1 2 3}" \
61 "0 {1 2 3 1 2 3 4 5 6}" \
62 "0 {1 2 3 1 2 3 4 5 6 1 2 3 4 5 6}" \
63 "0 {}" \
64 ]
65 set rc [expr [lsearch -exact $possible_results $res] >= 0]
66 if {$rc != 1} {
67 puts ""
68 puts "Result: $res"
69 }
70 set rc
71 } {1}
72 db2 close
73}
74
75do_ioerr_test shared_ioerr-2 -tclprep {
76 sqlite3 db2 test.db
77 execsql {
78 PRAGMA read_uncommitted = 1;
79 BEGIN;
80 CREATE TABLE t1(a, b);
81 INSERT INTO t1(oid) VALUES(NULL);
82 INSERT INTO t1(oid) SELECT NULL FROM t1;
83 INSERT INTO t1(oid) SELECT NULL FROM t1;
84 INSERT INTO t1(oid) SELECT NULL FROM t1;
85 INSERT INTO t1(oid) SELECT NULL FROM t1;
86 INSERT INTO t1(oid) SELECT NULL FROM t1;
87 INSERT INTO t1(oid) SELECT NULL FROM t1;
88 INSERT INTO t1(oid) SELECT NULL FROM t1;
89 INSERT INTO t1(oid) SELECT NULL FROM t1;
90 INSERT INTO t1(oid) SELECT NULL FROM t1;
91 INSERT INTO t1(oid) SELECT NULL FROM t1;
92 UPDATE t1 set a = oid, b = 'abcdefghijklmnopqrstuvwxyz0123456789';
93 CREATE INDEX i1 ON t1(a);
94 COMMIT;
95 BEGIN;
96 SELECT * FROM sqlite_master;
97 } db2
98} -tclbody {
99 set ::residx 0
100 execsql {DELETE FROM t1 WHERE 0 = (a % 2);}
101 incr ::residx
102
103 # When this transaction begins the table contains 512 entries. The
104 # two statements together add 512+146 more if it succeeds.
105 # (1024/7==146)
106 execsql {BEGIN;}
107 execsql {INSERT INTO t1 SELECT a+1, b FROM t1;}
108 execsql {INSERT INTO t1 SELECT 'string' || a, b FROM t1 WHERE 0 = (a%7);}
109 execsql {COMMIT;}
110
111 incr ::residx
112} -cleanup {
113 do_test shared_ioerr-2.$n.cleanup.1 {
114 set res [catchsql {
115 SELECT max(a), min(a), count(*) FROM (SELECT a FROM t1 order by a);
116 } db2]
117 set possible_results [list \
118 {0 {1024 1 1024}} \
119 {0 {1023 1 512}} \
120 {0 {string994 1 1170}} \
121 ]
122 set idx [lsearch -exact $possible_results $res]
123 set success [expr {$idx==$::residx || $res=="1 {disk I/O error}"}]
124 if {!$success} {
125 puts ""
126 puts "Result: \"$res\" ($::residx)"
127 }
128 set success
129 } {1}
130 db2 close
131}
132
danielk197797a227c2006-01-20 16:32:04 +0000133# This test is designed to provoke an IO error when a cursor position is
134# "saved" (because another cursor is going to modify the underlying table).
135#
136do_ioerr_test shared_ioerr-3 -tclprep {
137 sqlite3 db2 test.db
138 execsql {
139 PRAGMA read_uncommitted = 1;
140 BEGIN;
141 CREATE TABLE t1(a, b, UNIQUE(a, b));
142 } db2
143 for {set i 0} {$i < 5} {incr i} {
144 set a [string repeat $i 10]
145 set b [string repeat $i 2000]
146 execsql {INSERT INTO t1 VALUES($a, $b)} db2
147 }
148 execsql {COMMIT} db2
149 set ::DB2 [sqlite3_connection_pointer db2]
150 set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY]
151 sqlite3_step $::STMT ;# Cursor points at 0000000000
152 sqlite3_step $::STMT ;# Cursor points at 1111111111
153} -tclbody {
154 execsql {
155 INSERT INTO t1 VALUES(6, NULL);
156 }
157} -cleanup {
158 do_test shared_ioerr-3.$n.cleanup.1 {
159 sqlite3_step $::STMT
160 } {SQLITE_ROW}
161 do_test shared_ioerr-3.$n.cleanup.2 {
162 sqlite3_column_text $::STMT 0
163 } {2222222222}
164 do_test shared_ioerr-3.$n.cleanup.3 {
165 sqlite3_finalize $::STMT
166 } {SQLITE_OK}
167# db2 eval {select * from sqlite_master}
168 db2 close
169}
170
danielk197707cb5602006-01-20 10:55:05 +0000171catch {db close}
172sqlite3_enable_shared_cache $::enable_shared_cache
173finish_test
174