xref: /sqlite-3.40.0/test/shared_err.test (revision d0679edc)
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.13 2007/08/28 22:24:35 drh Exp $
17
18proc skip {args} {}
19
20
21set testdir [file dirname $argv0]
22source $testdir/tester.tcl
23source $testdir/malloc_common.tcl
24db close
25
26ifcapable !shared_cache||!subquery {
27  finish_test
28  return
29}
30
31set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
32
33do_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    ]
67    set rc [expr [lsearch -exact $possible_results $res] >= 0]
68    if {$rc != 1} {
69      puts ""
70      puts "Result: $res"
71    }
72    set rc
73  } {1}
74  db2 close
75}
76
77do_ioerr_test shared_ioerr-2 -tclprep {
78  sqlite3 db2 test.db
79  execsql {
80    PRAGMA read_uncommitted = 1;
81    BEGIN;
82    CREATE TABLE t1(a, b);
83    INSERT INTO t1(oid) VALUES(NULL);
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    INSERT INTO t1(oid) SELECT NULL FROM t1;
93    INSERT INTO t1(oid) SELECT NULL FROM t1;
94    UPDATE t1 set a = oid, b = 'abcdefghijklmnopqrstuvwxyz0123456789';
95    CREATE INDEX i1 ON t1(a);
96    COMMIT;
97    BEGIN;
98    SELECT * FROM sqlite_master;
99  } db2
100} -tclbody {
101  set ::residx 0
102  execsql {DELETE FROM t1 WHERE 0 = (a % 2);}
103  incr ::residx
104
105  # When this transaction begins the table contains 512 entries. The
106  # two statements together add 512+146 more if it succeeds.
107  # (1024/7==146)
108  execsql {BEGIN;}
109  execsql {INSERT INTO t1 SELECT a+1, b FROM t1;}
110  execsql {INSERT INTO t1 SELECT 'string' || a, b FROM t1 WHERE 0 = (a%7);}
111  execsql {COMMIT;}
112
113  incr ::residx
114} -cleanup {
115  do_test shared_ioerr-2.$n.cleanup.1 {
116    set res [catchsql {
117      SELECT max(a), min(a), count(*) FROM (SELECT a FROM t1 order by a);
118    } db2]
119    set possible_results [list \
120      {0 {1024 1 1024}}        \
121      {0 {1023 1 512}}         \
122      {0 {string994 1 1170}}   \
123    ]
124    set idx [lsearch -exact $possible_results $res]
125    set success [expr {$idx==$::residx || $res=="1 {disk I/O error}"}]
126    if {!$success} {
127      puts ""
128      puts "Result: \"$res\" ($::residx)"
129    }
130    set success
131  } {1}
132  db2 close
133}
134
135# This test is designed to provoke an IO error when a cursor position is
136# "saved" (because another cursor is going to modify the underlying table).
137#
138do_ioerr_test shared_ioerr-3 -tclprep {
139  sqlite3 db2 test.db
140  execsql {
141    PRAGMA read_uncommitted = 1;
142    PRAGMA cache_size = 10;
143    BEGIN;
144    CREATE TABLE t1(a, b, UNIQUE(a, b));
145  } db2
146  for {set i 0} {$i < 200} {incr i} {
147    set a [string range [string repeat "[format %03d $i]." 5] 0 end-1]
148
149    set b [string repeat $i 2000]
150    execsql {INSERT INTO t1 VALUES($a, $b)} db2
151  }
152  execsql {COMMIT} db2
153  set ::DB2 [sqlite3_connection_pointer db2]
154  set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY]
155  sqlite3_step $::STMT       ;# Cursor points at 000.000.000.000
156  sqlite3_step $::STMT       ;# Cursor points at 001.001.001.001
157
158} -tclbody {
159btree_breakpoint
160  execsql {
161    BEGIN;
162    INSERT INTO t1 VALUES('201.201.201.201.201', NULL);
163    UPDATE t1 SET a = '202.202.202.202.202' WHERE a LIKE '201%';
164    COMMIT;
165  }
166} -cleanup {
167  set ::steprc  [sqlite3_step $::STMT]
168  set ::column  [sqlite3_column_text $::STMT 0]
169  set ::finalrc [sqlite3_finalize $::STMT]
170
171  # There are three possible outcomes here (assuming persistent IO errors):
172  #
173  # 1. If the [sqlite3_step] did not require any IO (required pages in
174  #    the cache), then the next row ("002...") may be retrieved
175  #    successfully.
176  #
177  # 2. If the [sqlite3_step] does require IO, then [sqlite3_step] returns
178  #    SQLITE_ERROR and [sqlite3_finalize] returns IOERR.
179  #
180  # 3. If, after the initial IO error, SQLite tried to rollback the
181  #    active transaction and a second IO error was encountered, then
182  #    statement $::STMT will have been aborted. This means [sqlite3_stmt]
183  #    returns SQLITE_ABORT, and the statement cursor does not move. i.e.
184  #    [sqlite3_column] still returns the current row ("001...") and
185  #    [sqlite3_finalize] returns SQLITE_OK.
186  #
187
188  do_test shared_ioerr-3.$n.cleanup.1 {
189    expr {
190      $::steprc eq "SQLITE_ROW" ||
191      $::steprc eq "SQLITE_ERROR" ||
192      $::steprc eq "SQLITE_ABORT"
193    }
194  } {1}
195  do_test shared_ioerr-3.$n.cleanup.2 {
196    expr {
197      ($::steprc eq "SQLITE_ROW" && $::column eq "002.002.002.002.002") ||
198      ($::steprc eq "SQLITE_ERROR" && $::column eq "") ||
199      ($::steprc eq "SQLITE_ABORT" && $::column eq "001.001.001.001.001")
200    }
201  } {1}
202  do_test shared_ioerr-3.$n.cleanup.3 {
203    expr {
204      ($::steprc eq "SQLITE_ROW" && $::finalrc eq "SQLITE_OK") ||
205      ($::steprc eq "SQLITE_ERROR" && $::finalrc eq "SQLITE_IOERR") ||
206      ($::steprc eq "SQLITE_ABORT" && $::finalrc eq "SQLITE_OK")
207    }
208  } {1}
209
210# db2 eval {select * from sqlite_master}
211  db2 close
212}
213
214# This is a repeat of the previous test except that this time we
215# are doing a reverse-order scan of the table when the cursor is
216# "saved".
217#
218do_ioerr_test shared_ioerr-3rev -tclprep {
219  sqlite3 db2 test.db
220  execsql {
221    PRAGMA read_uncommitted = 1;
222    PRAGMA cache_size = 10;
223    BEGIN;
224    CREATE TABLE t1(a, b, UNIQUE(a, b));
225  } db2
226  for {set i 0} {$i < 200} {incr i} {
227    set a [string range [string repeat "[format %03d $i]." 5] 0 end-1]
228
229    set b [string repeat $i 2000]
230    execsql {INSERT INTO t1 VALUES($a, $b)} db2
231  }
232  execsql {COMMIT} db2
233  set ::DB2 [sqlite3_connection_pointer db2]
234  set ::STMT [sqlite3_prepare $::DB2 \
235           "SELECT a FROM t1 ORDER BY a DESC" -1 DUMMY]
236  sqlite3_step $::STMT       ;# Cursor points at 199.199.199.199.199
237  sqlite3_step $::STMT       ;# Cursor points at 198.198.198.198.198
238
239} -tclbody {
240  execsql {
241    BEGIN;
242    INSERT INTO t1 VALUES('201.201.201.201.201', NULL);
243    UPDATE t1 SET a = '202.202.202.202.202' WHERE a LIKE '201%';
244    COMMIT;
245  }
246} -cleanup {
247  set ::steprc  [sqlite3_step $::STMT]
248  set ::column  [sqlite3_column_text $::STMT 0]
249  set ::finalrc [sqlite3_finalize $::STMT]
250
251  # There are three possible outcomes here (assuming persistent IO errors):
252  #
253  # 1. If the [sqlite3_step] did not require any IO (required pages in
254  #    the cache), then the next row ("002...") may be retrieved
255  #    successfully.
256  #
257  # 2. If the [sqlite3_step] does require IO, then [sqlite3_step] returns
258  #    SQLITE_ERROR and [sqlite3_finalize] returns IOERR.
259  #
260  # 3. If, after the initial IO error, SQLite tried to rollback the
261  #    active transaction and a second IO error was encountered, then
262  #    statement $::STMT will have been aborted. This means [sqlite3_stmt]
263  #    returns SQLITE_ABORT, and the statement cursor does not move. i.e.
264  #    [sqlite3_column] still returns the current row ("001...") and
265  #    [sqlite3_finalize] returns SQLITE_OK.
266  #
267
268  do_test shared_ioerr-3rev.$n.cleanup.1 {
269    expr {
270      $::steprc eq "SQLITE_ROW" ||
271      $::steprc eq "SQLITE_ERROR" ||
272      $::steprc eq "SQLITE_ABORT"
273    }
274  } {1}
275  do_test shared_ioerr-3rev.$n.cleanup.2 {
276    expr {
277      ($::steprc eq "SQLITE_ROW" && $::column eq "197.197.197.197.197") ||
278      ($::steprc eq "SQLITE_ERROR" && $::column eq "") ||
279      ($::steprc eq "SQLITE_ABORT" && $::column eq "198.198.198.198.198")
280    }
281  } {1}
282  do_test shared_ioerr-3rev.$n.cleanup.3 {
283    expr {
284      ($::steprc eq "SQLITE_ROW" && $::finalrc eq "SQLITE_OK") ||
285      ($::steprc eq "SQLITE_ERROR" && $::finalrc eq "SQLITE_IOERR") ||
286      ($::steprc eq "SQLITE_ABORT" && $::finalrc eq "SQLITE_OK")
287    }
288  } {1}
289
290# db2 eval {select * from sqlite_master}
291  db2 close
292}
293
294# Only run these tests if memory debugging is turned on.
295#
296if {[info command sqlite_malloc_stat]==""} {
297   puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..."
298   db close
299   sqlite3_enable_shared_cache $::enable_shared_cache
300   finish_test
301   return
302}
303
304# Provoke a malloc() failure when a cursor position is being saved. This
305# only happens with index cursors (because they malloc() space to save the
306# current key value). It does not happen with tables, because an integer
307# key does not require a malloc() to store.
308#
309# The library should return an SQLITE_NOMEM to the caller. The query that
310# owns the cursor (the one for which the position is not saved) should
311# continue unaffected.
312#
313do_malloc_test 4 -tclprep {
314  sqlite3 db2 test.db
315  execsql {
316    PRAGMA read_uncommitted = 1;
317    BEGIN;
318    CREATE TABLE t1(a, b, UNIQUE(a, b));
319  } db2
320  for {set i 0} {$i < 5} {incr i} {
321    set a [string repeat $i 10]
322    set b [string repeat $i 2000]
323    execsql {INSERT INTO t1 VALUES($a, $b)} db2
324  }
325  execsql {COMMIT} db2
326  set ::DB2 [sqlite3_connection_pointer db2]
327  set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY]
328  sqlite3_step $::STMT       ;# Cursor points at 0000000000
329  sqlite3_step $::STMT       ;# Cursor points at 1111111111
330} -tclbody {
331  execsql {
332    INSERT INTO t1 VALUES(6, NULL);
333  }
334} -cleanup {
335  do_test shared_malloc-4.$::n.cleanup.1 {
336    set ::rc [sqlite3_step $::STMT]
337    expr {$::rc=="SQLITE_ROW" || $::rc=="SQLITE_ABORT"}
338  } {1}
339  if {$::rc=="SQLITE_ROW"} {
340    do_test shared_malloc-4.$::n.cleanup.2 {
341      sqlite3_column_text $::STMT 0
342    } {2222222222}
343  }
344  do_test shared_malloc-4.$::n.cleanup.3 {
345    sqlite3_finalize $::STMT
346  } {SQLITE_OK}
347# db2 eval {select * from sqlite_master}
348  db2 close
349}
350
351do_malloc_test 5 -tclbody {
352  sqlite3 dbX test.db
353  sqlite3 dbY test.db
354  dbX close
355  dbY close
356} -cleanup {
357  catch {dbX close}
358  catch {dbY close}
359}
360
361do_malloc_test 6 -tclbody {
362  catch {db close}
363  sqlite3_thread_cleanup
364  sqlite3_enable_shared_cache 0
365} -cleanup {
366  sqlite3_enable_shared_cache 1
367}
368
369do_test shared_misuse-7.1 {
370  sqlite3 db test.db
371  catch {
372    sqlite3_enable_shared_cache 0
373  } msg
374  set msg
375} {library routine called out of sequence}
376
377# Again provoke a malloc() failure when a cursor position is being saved,
378# this time during a ROLLBACK operation by some other handle.
379#
380# The library should return an SQLITE_NOMEM to the caller. The query that
381# owns the cursor (the one for which the position is not saved) should
382# be aborted.
383#
384set ::aborted 0
385do_malloc_test 8 -tclprep {
386  sqlite3 db2 test.db
387  execsql {
388    PRAGMA read_uncommitted = 1;
389    BEGIN;
390    CREATE TABLE t1(a, b, UNIQUE(a, b));
391  } db2
392  for {set i 0} {$i < 2} {incr i} {
393    set a [string repeat $i 10]
394    set b [string repeat $i 2000]
395    execsql {INSERT INTO t1 VALUES($a, $b)} db2
396  }
397  execsql {COMMIT} db2
398  set ::DB2 [sqlite3_connection_pointer db2]
399  set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY]
400  sqlite3_step $::STMT       ;# Cursor points at 0000000000
401  sqlite3_step $::STMT       ;# Cursor points at 1111111111
402} -tclbody {
403  execsql {
404    BEGIN;
405    INSERT INTO t1 VALUES(6, NULL);
406    ROLLBACK;
407  }
408} -cleanup {
409  do_test shared_malloc-8.$::n.cleanup.1 {
410    lrange [execsql {
411      SELECT a FROM t1;
412    } db2] 0 1
413  } {0000000000 1111111111}
414  do_test shared_malloc-8.$::n.cleanup.2 {
415    set rc1 [sqlite3_step $::STMT]
416    set rc2 [sqlite3_finalize $::STMT]
417    if {$rc1=="SQLITE_ABORT"} {
418      incr ::aborted
419    }
420    expr {
421      ($rc1=="SQLITE_DONE" && $rc2=="SQLITE_OK") ||
422      ($rc1=="SQLITE_ABORT" && $rc2=="SQLITE_OK")
423    }
424  } {1}
425  db2 close
426}
427do_test shared_malloc-8.X {
428  # Test that one or more queries were aborted due to the malloc() failure.
429  expr $::aborted>=1
430} {1}
431
432catch {db close}
433sqlite3_enable_shared_cache $::enable_shared_cache
434finish_test
435