xref: /sqlite-3.40.0/test/ioerr.test (revision 37c906e6)
181a20f21Sdrh# 2001 October 12
281a20f21Sdrh#
381a20f21Sdrh# The author disclaims copyright to this source code.  In place of
481a20f21Sdrh# a legal notice, here is a blessing:
581a20f21Sdrh#
681a20f21Sdrh#    May you do good and not evil.
781a20f21Sdrh#    May you find forgiveness for yourself and forgive others.
881a20f21Sdrh#    May you share freely, never taking more than you give.
981a20f21Sdrh#
1081a20f21Sdrh#***********************************************************************
1181a20f21Sdrh# This file implements regression tests for SQLite library.  The
1281a20f21Sdrh# focus of this file is testing for correct handling of I/O errors
1381a20f21Sdrh# such as writes failing because the disk is full.
1481a20f21Sdrh#
1581a20f21Sdrh# The tests in this file use special facilities that are only
1681a20f21Sdrh# available in the SQLite test fixture.
1781a20f21Sdrh#
18ef165cedSdanielk1977# $Id: ioerr.test,v 1.43 2009/04/06 17:50:03 danielk1977 Exp $
1981a20f21Sdrh
2081a20f21Sdrhset testdir [file dirname $argv0]
2181a20f21Sdrhsource $testdir/tester.tcl
2281a20f21Sdrh
2359adfaa6Sdanielk1977# If SQLITE_DEFAULT_AUTOVACUUM is set to true, then a simulated IO error
2459adfaa6Sdanielk1977# on the 8th IO operation in the SQL script below doesn't report an error.
2559adfaa6Sdanielk1977#
2659adfaa6Sdanielk1977# This is because the 8th IO call attempts to read page 2 of the database
2759adfaa6Sdanielk1977# file when the file on disk is only 1 page. The pager layer detects that
2859adfaa6Sdanielk1977# this has happened and suppresses the error returned by the OS layer.
2959adfaa6Sdanielk1977#
304abd5449Sdanielk1977do_ioerr_test ioerr-1 -erc 1 -ckrefcount 1 -sqlprep {
318b60e0f1Sdanielk1977  SELECT * FROM sqlite_master;
328b60e0f1Sdanielk1977} -sqlbody {
3381a20f21Sdrh  CREATE TABLE t1(a,b,c);
3481a20f21Sdrh  SELECT * FROM sqlite_master;
3581a20f21Sdrh  BEGIN TRANSACTION;
3681a20f21Sdrh  INSERT INTO t1 VALUES(1,2,3);
3781a20f21Sdrh  INSERT INTO t1 VALUES(4,5,6);
3881a20f21Sdrh  ROLLBACK;
3981a20f21Sdrh  SELECT * FROM t1;
4081a20f21Sdrh  BEGIN TRANSACTION;
4181a20f21Sdrh  INSERT INTO t1 VALUES(1,2,3);
4281a20f21Sdrh  INSERT INTO t1 VALUES(4,5,6);
4381a20f21Sdrh  COMMIT;
4481a20f21Sdrh  SELECT * FROM t1;
4581a20f21Sdrh  DELETE FROM t1 WHERE a<100;
46f2fa8310Sdanielk1977} -exclude [expr [string match [execsql {pragma auto_vacuum}] 1] ? 4 : 0]
478b60e0f1Sdanielk1977
4832554c10Sdanielk1977# Test for IO errors during a VACUUM.
4932554c10Sdanielk1977#
5032554c10Sdanielk1977# The first IO call is excluded from the test. This call attempts to read
5132554c10Sdanielk1977# the file-header of the temporary database used by VACUUM. Since the
5232554c10Sdanielk1977# database doesn't exist at that point, the IO error is not detected.
5332554c10Sdanielk1977#
5432554c10Sdanielk1977# Additionally, if auto-vacuum is enabled, the 12th IO error is not
5532554c10Sdanielk1977# detected. Same reason as the 8th in the test case above.
5632554c10Sdanielk1977#
570fa388f6Sdanielk1977ifcapable vacuum {
584abd5449Sdanielk1977  do_ioerr_test ioerr-2 -cksum true -ckrefcount true -sqlprep {
592e6d11bcSdrh    BEGIN;
602e6d11bcSdrh    CREATE TABLE t1(a, b, c);
61f7c9bfeaSdanielk1977    INSERT INTO t1 VALUES(1, randstr(50,50), randstr(50,50));
622e6d11bcSdrh    INSERT INTO t1 SELECT a+2, b||'-'||rowid, c||'-'||rowid FROM t1;
632e6d11bcSdrh    INSERT INTO t1 SELECT a+4, b||'-'||rowid, c||'-'||rowid FROM t1;
642e6d11bcSdrh    INSERT INTO t1 SELECT a+8, b||'-'||rowid, c||'-'||rowid FROM t1;
652e6d11bcSdrh    INSERT INTO t1 SELECT a+16, b||'-'||rowid, c||'-'||rowid FROM t1;
662e6d11bcSdrh    INSERT INTO t1 SELECT a+32, b||'-'||rowid, c||'-'||rowid FROM t1;
672e6d11bcSdrh    INSERT INTO t1 SELECT a+64, b||'-'||rowid, c||'-'||rowid FROM t1;
682e6d11bcSdrh    INSERT INTO t1 SELECT a+128, b||'-'||rowid, c||'-'||rowid FROM t1;
697701e817Sdanielk1977    INSERT INTO t1 VALUES(1, randstr(600,600), randstr(600,600));
702e6d11bcSdrh    CREATE TABLE t2 AS SELECT * FROM t1;
712e6d11bcSdrh    CREATE TABLE t3 AS SELECT * FROM t1;
722e6d11bcSdrh    COMMIT;
732e6d11bcSdrh    DROP TABLE t2;
7432554c10Sdanielk1977  } -sqlbody {
752e6d11bcSdrh    VACUUM;
7632554c10Sdanielk1977  } -exclude [list \
77f2fa8310Sdanielk1977      1 [expr [string match [execsql {pragma auto_vacuum}] 1]?9:-1]]
780fa388f6Sdanielk1977}
7981a20f21Sdrh
804abd5449Sdanielk1977do_ioerr_test ioerr-3 -ckrefcount true -tclprep {
812812956bSdanielk1977  execsql {
822812956bSdanielk1977    PRAGMA cache_size = 10;
832812956bSdanielk1977    BEGIN;
842812956bSdanielk1977    CREATE TABLE abc(a);
852812956bSdanielk1977    INSERT INTO abc VALUES(randstr(1500,1500)); -- Page 4 is overflow
862812956bSdanielk1977  }
872812956bSdanielk1977  for {set i 0} {$i<150} {incr i} {
882812956bSdanielk1977    execsql {
892812956bSdanielk1977      INSERT INTO abc VALUES(randstr(100,100));
902812956bSdanielk1977    }
912812956bSdanielk1977  }
922812956bSdanielk1977  execsql COMMIT
938b60e0f1Sdanielk1977} -sqlbody {
942812956bSdanielk1977  CREATE TABLE abc2(a);
952812956bSdanielk1977  BEGIN;
962812956bSdanielk1977  DELETE FROM abc WHERE length(a)>100;
972812956bSdanielk1977  UPDATE abc SET a = randstr(90,90);
982812956bSdanielk1977  COMMIT;
992812956bSdanielk1977  CREATE TABLE abc3(a);
1002812956bSdanielk1977}
1012812956bSdanielk1977
1028b60e0f1Sdanielk1977# Test IO errors that can occur retrieving a record header that flows over
1038b60e0f1Sdanielk1977# onto an overflow page.
1044abd5449Sdanielk1977do_ioerr_test ioerr-4 -ckrefcount true -tclprep {
10501427a62Sdanielk1977  set sql "CREATE TABLE abc(a1"
10601427a62Sdanielk1977  for {set i 2} {$i<1300} {incr i} {
10701427a62Sdanielk1977    append sql ", a$i"
10801427a62Sdanielk1977  }
10901427a62Sdanielk1977  append sql ");"
11001427a62Sdanielk1977  execsql $sql
11101427a62Sdanielk1977  execsql {INSERT INTO abc (a1) VALUES(NULL)}
1128b60e0f1Sdanielk1977} -sqlbody {
11301427a62Sdanielk1977 SELECT * FROM abc;
11401427a62Sdanielk1977}
1158b60e0f1Sdanielk1977
116861f7456Sdanielk1977
1178b60e0f1Sdanielk1977# Test IO errors that may occur during a multi-file commit.
118aca790acSdanielk1977#
119aac0a38dSdanielk1977# Tests 8 and 17 are excluded when auto-vacuum is enabled for the same
120aac0a38dSdanielk1977# reason as in test cases ioerr-1.XXX
1215a8f9374Sdanielk1977ifcapable attach {
122aac0a38dSdanielk1977  set ex ""
123aac0a38dSdanielk1977  if {[string match [execsql {pragma auto_vacuum}] 1]} {
124f2fa8310Sdanielk1977    set ex [list 4 17]
125aac0a38dSdanielk1977  }
126861f7456Sdanielk1977  do_ioerr_test ioerr-5 -restoreprng 0 -ckrefcount true -sqlprep {
1278b60e0f1Sdanielk1977    ATTACH 'test2.db' AS test2;
1288b60e0f1Sdanielk1977  } -sqlbody {
1298b60e0f1Sdanielk1977    BEGIN;
1308b60e0f1Sdanielk1977    CREATE TABLE t1(a,b,c);
1318b60e0f1Sdanielk1977    CREATE TABLE test2.t2(a,b,c);
1328b60e0f1Sdanielk1977    COMMIT;
133aac0a38dSdanielk1977  } -exclude $ex
1345a8f9374Sdanielk1977}
135aca790acSdanielk1977
136aca790acSdanielk1977# Test IO errors when replaying two hot journals from a 2-file
137aca790acSdanielk1977# transaction. This test only runs on UNIX.
138b4eb82f6Sdan#
139b4eb82f6Sdan# It cannot be run under the "exclusive" permutation. In that case, the
140b4eb82f6Sdan# locks held by the connection in the local (this) process prevent a
141b4eb82f6Sdan# second connection from attempting the multi-file transaction.
142b4eb82f6Sdan#
1435a8f9374Sdanielk1977ifcapable crashtest&&attach {
144b4eb82f6Sdan  if {![catch {sqlite3 -has-codec} r] && !$r && [permutation]!="exclusive"} {
1454abd5449Sdanielk1977    do_ioerr_test ioerr-6 -ckrefcount true -tclprep {
14632554c10Sdanielk1977      execsql {
14732554c10Sdanielk1977        ATTACH 'test2.db' as aux;
14832554c10Sdanielk1977        CREATE TABLE tx(a, b);
14932554c10Sdanielk1977        CREATE TABLE aux.ty(a, b);
15032554c10Sdanielk1977      }
15159a33f98Sdanielk1977      set rc [crashsql -delay 2 -file test2.db-journal {
152aca790acSdanielk1977        ATTACH 'test2.db' as aux;
153aca790acSdanielk1977        PRAGMA cache_size = 10;
154aca790acSdanielk1977        BEGIN;
155aca790acSdanielk1977        CREATE TABLE aux.t2(a, b, c);
156aca790acSdanielk1977        CREATE TABLE t1(a, b, c);
157aca790acSdanielk1977        COMMIT;
158aca790acSdanielk1977      }]
159aca790acSdanielk1977      if {$rc!="1 {child process exited abnormally}"} {
160aca790acSdanielk1977        error "Wrong error message: $rc"
161aca790acSdanielk1977      }
162aca790acSdanielk1977    } -sqlbody {
16332554c10Sdanielk1977      SELECT * FROM sqlite_master;
16432554c10Sdanielk1977      SELECT * FROM aux.sqlite_master;
165aca790acSdanielk1977    }
1668b60e0f1Sdanielk1977  }
16766560adaSdrh}
16801427a62Sdanielk1977
169aca790acSdanielk1977# Test handling of IO errors that occur while rolling back hot journal
170aca790acSdanielk1977# files.
171ca670714Sdanielk1977#
172ca670714Sdanielk1977# These tests can't be run on windows because the windows version of
173ca670714Sdanielk1977# SQLite holds a mandatory exclusive lock on journal files it has open.
174ca670714Sdanielk1977#
1750aac5613Sdanif {$tcl_platform(platform)!="windows" && ![atomic_batch_write test.db]} {
17632554c10Sdanielk1977  do_ioerr_test ioerr-7 -tclprep {
177aca790acSdanielk1977    db close
178aca790acSdanielk1977    sqlite3 db2 test2.db
179aca790acSdanielk1977    db2 eval {
180aca790acSdanielk1977      PRAGMA synchronous = 0;
181aca790acSdanielk1977      CREATE TABLE t1(a, b);
182aca790acSdanielk1977      INSERT INTO t1 VALUES(1, 2);
183aca790acSdanielk1977      BEGIN;
184aca790acSdanielk1977      INSERT INTO t1 VALUES(3, 4);
185aca790acSdanielk1977    }
186fda06befSmistachkin    forcecopy test2.db test.db
187fda06befSmistachkin    forcecopy test2.db-journal test.db-journal
188aca790acSdanielk1977    db2 close
189aca790acSdanielk1977  } -tclbody {
190aca790acSdanielk1977    sqlite3 db test.db
191aca790acSdanielk1977    db eval {
192aca790acSdanielk1977      SELECT * FROM t1;
193aca790acSdanielk1977    }
194aca790acSdanielk1977  } -exclude 1
195ca670714Sdanielk1977}
196aca790acSdanielk1977
197f0bce09cSdrh# For test coverage:  Cause an I/O failure while trying to read a
198f0bce09cSdrh# short field (one that fits into a Mem buffer without mallocing
199f0bce09cSdrh# for space).
200f0bce09cSdrh#
2014abd5449Sdanielk1977do_ioerr_test ioerr-8 -ckrefcount true -tclprep {
202f0bce09cSdrh  execsql {
203f0bce09cSdrh    CREATE TABLE t1(a,b,c);
204f0bce09cSdrh    INSERT INTO t1 VALUES(randstr(200,200), randstr(1000,1000), 2);
205f0bce09cSdrh  }
206f0bce09cSdrh  db close
207f0bce09cSdrh  sqlite3 db test.db
208f0bce09cSdrh} -sqlbody {
209f0bce09cSdrh  SELECT c FROM t1;
210f0bce09cSdrh}
211f0bce09cSdrh
2128a7aea3bSdanielk1977# For test coverage: Cause an IO error whilst reading the master-journal
2138a7aea3bSdanielk1977# name from a journal file.
2140aac5613Sdanif {$tcl_platform(platform)=="unix" && [atomic_batch_write test.db]==0} {
2154abd5449Sdanielk1977  do_ioerr_test ioerr-9 -ckrefcount true -tclprep {
2168a7aea3bSdanielk1977    execsql {
2178a7aea3bSdanielk1977      CREATE TABLE t1(a,b,c);
2188a7aea3bSdanielk1977      INSERT INTO t1 VALUES(randstr(200,200), randstr(1000,1000), 2);
2198a7aea3bSdanielk1977      BEGIN;
2208a7aea3bSdanielk1977      INSERT INTO t1 VALUES(randstr(200,200), randstr(1000,1000), 2);
2218a7aea3bSdanielk1977    }
222fda06befSmistachkin    forcecopy test.db-journal test2.db-journal
2238a7aea3bSdanielk1977    execsql {
2248a7aea3bSdanielk1977      COMMIT;
2258a7aea3bSdanielk1977    }
226fda06befSmistachkin    forcecopy test2.db-journal test.db-journal
2278a7aea3bSdanielk1977    set f [open test.db-journal a]
2288a7aea3bSdanielk1977    fconfigure $f -encoding binary
2298a7aea3bSdanielk1977    puts -nonewline $f "hello"
2308a7aea3bSdanielk1977    puts -nonewline $f "\x00\x00\x00\x05\x01\x02\x03\x04"
2318a7aea3bSdanielk1977    puts -nonewline $f "\xd9\xd5\x05\xf9\x20\xa1\x63\xd7"
2328a7aea3bSdanielk1977    close $f
2338a7aea3bSdanielk1977  } -sqlbody {
2348a7aea3bSdanielk1977    SELECT a FROM t1;
2358a7aea3bSdanielk1977  }
236be1f84c0Sdrh}
2378a7aea3bSdanielk1977
2388a7aea3bSdanielk1977# For test coverage: Cause an IO error during statement playback (i.e.
2398a7aea3bSdanielk1977# a constraint).
2404abd5449Sdanielk1977do_ioerr_test ioerr-10 -ckrefcount true -tclprep {
2418a7aea3bSdanielk1977  execsql {
2428a7aea3bSdanielk1977    BEGIN;
2438a7aea3bSdanielk1977    CREATE TABLE t1(a PRIMARY KEY, b);
2448a7aea3bSdanielk1977  }
2458a7aea3bSdanielk1977  for {set i 0} {$i < 500} {incr i} {
24612f5e201Sdanielk1977    execsql {INSERT INTO t1 VALUES(:i, 'hello world');}
2478a7aea3bSdanielk1977  }
2488a7aea3bSdanielk1977  execsql {
2498a7aea3bSdanielk1977    COMMIT;
2508a7aea3bSdanielk1977  }
2518a7aea3bSdanielk1977} -tclbody {
2528a7aea3bSdanielk1977
2538a7aea3bSdanielk1977  catch {execsql {
2548a7aea3bSdanielk1977    BEGIN;
2558a7aea3bSdanielk1977    INSERT INTO t1 VALUES('abc', 123);
2568a7aea3bSdanielk1977    INSERT INTO t1 VALUES('def', 123);
2578a7aea3bSdanielk1977    INSERT INTO t1 VALUES('ghi', 123);
2588a7aea3bSdanielk1977    INSERT INTO t1 SELECT (a+500)%900, 'good string' FROM t1;
2598a7aea3bSdanielk1977  }} msg
2608a7aea3bSdanielk1977
2611b4b334aSdan  if {$msg != "UNIQUE constraint failed: t1.a"} {
2628a7aea3bSdanielk1977    error $msg
2638a7aea3bSdanielk1977  }
2648a7aea3bSdanielk1977}
2658a7aea3bSdanielk1977
266d5eb79ebSdrh# Assertion fault bug reported by alex dimitrov.
267d5eb79ebSdrh#
2684abd5449Sdanielk1977do_ioerr_test ioerr-11 -ckrefcount true -erc 1 -sqlprep {
269d5eb79ebSdrh   CREATE TABLE A(Id INTEGER, Name TEXT);
270d5eb79ebSdrh   INSERT INTO A(Id, Name) VALUES(1, 'Name');
271d5eb79ebSdrh} -sqlbody {
272d5eb79ebSdrh   UPDATE A SET Id = 2, Name = 'Name2' WHERE Id = 1;
273d5eb79ebSdrh}
274d5eb79ebSdrh
275d7d2f93cSdanielk1977# Test that an io error encountered in a sync() caused by a call to
276d7d2f93cSdanielk1977# sqlite3_release_memory() is handled Ok. Only try this if
277d7d2f93cSdanielk1977# memory-management is enabled.
278d7d2f93cSdanielk1977#
279d7d2f93cSdanielk1977ifcapable memorymanage {
2804abd5449Sdanielk1977  do_ioerr_test memmanage-ioerr1 -ckrefcount true -sqlprep {
281d7d2f93cSdanielk1977    BEGIN;
282d7d2f93cSdanielk1977    CREATE TABLE t1(a, b, c);
283d7d2f93cSdanielk1977    INSERT INTO t1 VALUES(randstr(50,50), randstr(100,100), randstr(10,10));
284d7d2f93cSdanielk1977    INSERT INTO t1 SELECT randstr(50,50), randstr(9,9), randstr(90,90) FROM t1;
285d7d2f93cSdanielk1977    INSERT INTO t1 SELECT randstr(50,50), randstr(9,9), randstr(90,90) FROM t1;
286d7d2f93cSdanielk1977    INSERT INTO t1 SELECT randstr(50,50), randstr(9,9), randstr(90,90) FROM t1;
287d7d2f93cSdanielk1977    INSERT INTO t1 SELECT randstr(50,50), randstr(9,9), randstr(90,90) FROM t1;
288d7d2f93cSdanielk1977    INSERT INTO t1 SELECT randstr(50,50), randstr(9,9), randstr(90,90) FROM t1;
289d7d2f93cSdanielk1977  } -tclbody {
290d7d2f93cSdanielk1977    sqlite3_release_memory
291d7d2f93cSdanielk1977  } -sqlbody {
292d7d2f93cSdanielk1977    COMMIT;
293d7d2f93cSdanielk1977  }
294d7d2f93cSdanielk1977}
295d7d2f93cSdanielk1977
2963aa4b67fSdanielk1977ifcapable pager_pragmas&&autovacuum {
2973aa4b67fSdanielk1977  do_ioerr_test ioerr-12 -ckrefcount true -erc 1 -sqlprep {
2983aa4b67fSdanielk1977     PRAGMA page_size = 512;
2993aa4b67fSdanielk1977     PRAGMA auto_vacuum = incremental;
3003aa4b67fSdanielk1977     CREATE TABLE t1(x);
3013aa4b67fSdanielk1977     INSERT INTO t1 VALUES( randomblob(1   * (512-4)) );
3023aa4b67fSdanielk1977     INSERT INTO t1 VALUES( randomblob(110 * (512-4)) );
3033aa4b67fSdanielk1977     INSERT INTO t1 VALUES( randomblob(2   * (512-4)) );
3043aa4b67fSdanielk1977     INSERT INTO t1 VALUES( randomblob(110 * (512-4)) );
3053aa4b67fSdanielk1977     INSERT INTO t1 VALUES( randomblob(3 * (512-4)) );
3063aa4b67fSdanielk1977     DELETE FROM t1 WHERE rowid = 3;
3073aa4b67fSdanielk1977     PRAGMA incremental_vacuum = 2;
3083aa4b67fSdanielk1977     DELETE FROM t1 WHERE rowid = 1;
3093aa4b67fSdanielk1977  } -sqlbody {
3103aa4b67fSdanielk1977     PRAGMA incremental_vacuum = 1;
3113aa4b67fSdanielk1977  }
3123aa4b67fSdanielk1977}
3133aa4b67fSdanielk1977
3141bc71590Sdanielk1977# Usually, after a new page is allocated from the end of the file, it does
3151bc71590Sdanielk1977# not need to be written to the journal. The exception is when the new page
3161bc71590Sdanielk1977# shares its sector with an existing page that does need to be journalled.
3171bc71590Sdanielk1977# This test case provokes this condition to test for the sake of coverage
3181bc71590Sdanielk1977# that an IO error while journalling the coresident page is handled correctly.
3191bc71590Sdanielk1977#
3201bc71590Sdanielk1977sqlite3_simulate_device -char {} -sectorsize 2048
3211bc71590Sdanielk1977do_ioerr_test ioerr-12 -ckrefcount true -erc 1 -tclprep {
3221bc71590Sdanielk1977  db close
3231bc71590Sdanielk1977  sqlite3 db test.db -vfs devsym
3241bc71590Sdanielk1977
3251bc71590Sdanielk1977  # Create a test database. Page 2 is the root page of table t1. The only
3261bc71590Sdanielk1977  # row inserted into t1 has an overflow page - page 3. Page 3 will be
3271bc71590Sdanielk1977  # coresident on the 2048 byte sector with the next page to be allocated.
3281bc71590Sdanielk1977  #
3291bc71590Sdanielk1977  db eval { PRAGMA page_size = 1024 }
3301bc71590Sdanielk1977  db eval { CREATE TABLE t1(x) }
3311bc71590Sdanielk1977  db eval { INSERT INTO t1 VALUES(randomblob(1100)); }
3321bc71590Sdanielk1977} -tclbody {
3331bc71590Sdanielk1977  db eval { INSERT INTO t1 VALUES(randomblob(2000)); }
3341bc71590Sdanielk1977}
3351bc71590Sdanielk1977sqlite3_simulate_device -char {} -sectorsize 0
336474b7cc7Sdanielk1977catch {db close}
337*37c906e6Sdanunregister_devsim
338474b7cc7Sdanielk1977
339474b7cc7Sdanielk1977do_ioerr_test ioerr-13 -ckrefcount true -erc 1 -sqlprep {
340474b7cc7Sdanielk1977  PRAGMA auto_vacuum = incremental;
341474b7cc7Sdanielk1977  CREATE TABLE t1(x);
342474b7cc7Sdanielk1977  CREATE TABLE t2(x);
343474b7cc7Sdanielk1977  INSERT INTO t2 VALUES(randomblob(1500));
344474b7cc7Sdanielk1977  INSERT INTO t2 SELECT randomblob(1500) FROM t2;
345474b7cc7Sdanielk1977  INSERT INTO t2 SELECT randomblob(1500) FROM t2;
346474b7cc7Sdanielk1977  INSERT INTO t2 SELECT randomblob(1500) FROM t2;
347474b7cc7Sdanielk1977  INSERT INTO t2 SELECT randomblob(1500) FROM t2;
348474b7cc7Sdanielk1977  INSERT INTO t2 SELECT randomblob(1500) FROM t2;
349474b7cc7Sdanielk1977  INSERT INTO t2 SELECT randomblob(1500) FROM t2;
350474b7cc7Sdanielk1977  INSERT INTO t2 SELECT randomblob(1500) FROM t2;
351474b7cc7Sdanielk1977  INSERT INTO t2 SELECT randomblob(1500) FROM t2;
352474b7cc7Sdanielk1977  INSERT INTO t1 VALUES(randomblob(20));
353474b7cc7Sdanielk1977  INSERT INTO t1 SELECT x FROM t1;
354474b7cc7Sdanielk1977  INSERT INTO t1 SELECT x FROM t1;
355474b7cc7Sdanielk1977  INSERT INTO t1 SELECT x FROM t1;
356474b7cc7Sdanielk1977  INSERT INTO t1 SELECT x FROM t1;
357474b7cc7Sdanielk1977  INSERT INTO t1 SELECT x FROM t1;
358474b7cc7Sdanielk1977  INSERT INTO t1 SELECT x FROM t1;             /* 64 entries in t1 */
359474b7cc7Sdanielk1977  INSERT INTO t1 SELECT x FROM t1 LIMIT 14;    /* 78 entries in t1 */
360474b7cc7Sdanielk1977  DELETE FROM t2 WHERE rowid = 3;
361474b7cc7Sdanielk1977} -sqlbody {
362474b7cc7Sdanielk1977  -- This statement uses the balance_quick() optimization. The new page
363474b7cc7Sdanielk1977  -- is appended to the database file. But the overflow page used by
364474b7cc7Sdanielk1977  -- the new record will be positioned near the start of the database
365474b7cc7Sdanielk1977  -- file, in the gap left by the "DELETE FROM t2 WHERE rowid=3" statement
366474b7cc7Sdanielk1977  -- above.
367474b7cc7Sdanielk1977  --
368474b7cc7Sdanielk1977  -- The point of this is that the statement wil need to update two pointer
369474b7cc7Sdanielk1977  -- map pages. Which introduces another opportunity for an IO error.
370474b7cc7Sdanielk1977  --
371474b7cc7Sdanielk1977  INSERT INTO t1 VALUES(randomblob(2000));
372474b7cc7Sdanielk1977}
373474b7cc7Sdanielk1977
374474b7cc7Sdanielk1977do_ioerr_test ioerr-14 -ckrefcount true -erc 1 -sqlprep {
375474b7cc7Sdanielk1977  PRAGMA auto_vacuum = incremental;
376474b7cc7Sdanielk1977  CREATE TABLE t1(x);
377474b7cc7Sdanielk1977  CREATE TABLE t2(x);
378474b7cc7Sdanielk1977  INSERT INTO t2 VALUES(randomblob(1500));
379474b7cc7Sdanielk1977  INSERT INTO t2 SELECT randomblob(1500) FROM t2;
380474b7cc7Sdanielk1977  INSERT INTO t2 SELECT randomblob(1500) FROM t2;
381474b7cc7Sdanielk1977  INSERT INTO t2 SELECT randomblob(1500) FROM t2;
382474b7cc7Sdanielk1977  INSERT INTO t2 SELECT randomblob(1500) FROM t2;
383474b7cc7Sdanielk1977  INSERT INTO t2 SELECT randomblob(1500) FROM t2;
384474b7cc7Sdanielk1977  INSERT INTO t2 SELECT randomblob(1500) FROM t2;
385474b7cc7Sdanielk1977  INSERT INTO t2 SELECT randomblob(1500) FROM t2;
386474b7cc7Sdanielk1977  INSERT INTO t2 SELECT randomblob(1500) FROM t2;
387474b7cc7Sdanielk1977
388474b7cc7Sdanielk1977  -- This statement inserts a row into t1 with an overflow page at the
389474b7cc7Sdanielk1977  -- end of the file. A long way from its parent (the root of t1).
390474b7cc7Sdanielk1977  INSERT INTO t1 VALUES(randomblob(1500));
391474b7cc7Sdanielk1977  DELETE FROM t2 WHERE rowid<10;
392474b7cc7Sdanielk1977} -sqlbody {
393474b7cc7Sdanielk1977  -- This transaction will cause the root-page of table t1 to divide
394474b7cc7Sdanielk1977  -- (by calling balance_deeper()). When it does, the "parent" page of the
395474b7cc7Sdanielk1977  -- overflow page inserted in the -sqlprep block above will change and
396474b7cc7Sdanielk1977  -- the corresponding pointer map page be updated. This test case attempts
397474b7cc7Sdanielk1977  -- to cause an IO error during the pointer map page update.
398474b7cc7Sdanielk1977  --
399474b7cc7Sdanielk1977  BEGIN;
400474b7cc7Sdanielk1977  INSERT INTO t1 VALUES(randomblob(100));
401474b7cc7Sdanielk1977  INSERT INTO t1 VALUES(randomblob(100));
402474b7cc7Sdanielk1977  INSERT INTO t1 VALUES(randomblob(100));
403474b7cc7Sdanielk1977  INSERT INTO t1 VALUES(randomblob(100));
404474b7cc7Sdanielk1977  INSERT INTO t1 VALUES(randomblob(100));
405474b7cc7Sdanielk1977  INSERT INTO t1 VALUES(randomblob(100));
406474b7cc7Sdanielk1977  INSERT INTO t1 VALUES(randomblob(100));
407474b7cc7Sdanielk1977  INSERT INTO t1 VALUES(randomblob(100));
408474b7cc7Sdanielk1977  INSERT INTO t1 VALUES(randomblob(100));
409474b7cc7Sdanielk1977  INSERT INTO t1 VALUES(randomblob(100));
410474b7cc7Sdanielk1977  COMMIT;
411474b7cc7Sdanielk1977}
4121bc71590Sdanielk1977
41336e20936Sdanielk1977do_ioerr_test ioerr-15 -tclprep {
41436e20936Sdanielk1977  db eval {
41536e20936Sdanielk1977    BEGIN;
41636e20936Sdanielk1977    PRAGMA cache_size = 10;
41736e20936Sdanielk1977    CREATE TABLE t1(a);
41836e20936Sdanielk1977    CREATE INDEX i1 ON t1(a);
41936e20936Sdanielk1977    CREATE TABLE t2(a);
42036e20936Sdanielk1977  }
42136e20936Sdanielk1977  for {set ii 1} {$ii < 100} {incr ii} {
42236e20936Sdanielk1977    set v [string range [string repeat [format %.3d $ii] 200] 0 220]
42336e20936Sdanielk1977    db eval {INSERT INTO t1 VALUES($v)}
42436e20936Sdanielk1977  }
42536e20936Sdanielk1977  db eval {
42636e20936Sdanielk1977    DELETE FROM t1 WHERE oid > 85;
42736e20936Sdanielk1977    COMMIT;
42836e20936Sdanielk1977  }
42936e20936Sdanielk1977} -sqlbody {
43036e20936Sdanielk1977  BEGIN;
43136e20936Sdanielk1977  INSERT INTO t2 VALUES(randstr(22000,22000));
43236e20936Sdanielk1977  DELETE FROM t1 WHERE oid = 83;
43336e20936Sdanielk1977  COMMIT;
43436e20936Sdanielk1977}
43536e20936Sdanielk1977
436ef165cedSdanielk1977# This test verifies that IO errors that occur within the obscure branch
437ef165cedSdanielk1977# of code executed by tkt3762.test are correctly reported.
438ef165cedSdanielk1977#
439ef165cedSdanielk1977ifcapable vacuum&&autovacuum&&pragma {
440ef165cedSdanielk1977  do_ioerr_test ioerr-16 -erc 1 -ckrefcount 1 -sqlprep {
441ef165cedSdanielk1977    PRAGMA auto_vacuum=INCREMENTAL;
442ef165cedSdanielk1977    PRAGMA page_size=1024;
443ef165cedSdanielk1977    BEGIN;
444ef165cedSdanielk1977    CREATE TABLE t1(x);
445ef165cedSdanielk1977    INSERT INTO t1 VALUES(zeroblob(900));
446ef165cedSdanielk1977    INSERT INTO t1 VALUES(zeroblob(900));
447ef165cedSdanielk1977    INSERT INTO t1 SELECT x FROM t1;
448ef165cedSdanielk1977    INSERT INTO t1 SELECT x FROM t1;
449ef165cedSdanielk1977    INSERT INTO t1 SELECT x FROM t1;
450ef165cedSdanielk1977    INSERT INTO t1 SELECT x FROM t1;
451ef165cedSdanielk1977    INSERT INTO t1 SELECT x FROM t1;
452ef165cedSdanielk1977    INSERT INTO t1 SELECT x FROM t1;
453ef165cedSdanielk1977    INSERT INTO t1 SELECT x FROM t1;
454ef165cedSdanielk1977    DELETE FROM t1 WHERE rowid>202;
455ef165cedSdanielk1977    COMMIT;
456ef165cedSdanielk1977    VACUUM;
457ef165cedSdanielk1977    PRAGMA cache_size = 10;
458ef165cedSdanielk1977    BEGIN;
459ef165cedSdanielk1977    DELETE FROM t1 WHERE rowid IN (10,11,12) ;
460ef165cedSdanielk1977  } -sqlbody {
461ef165cedSdanielk1977    PRAGMA incremental_vacuum(10);
462ef165cedSdanielk1977    COMMIT;
463ef165cedSdanielk1977  }
464ef165cedSdanielk1977}
465ef165cedSdanielk1977
46681a20f21Sdrhfinish_test
467