| Index: third_party/sqlite/src/test/pager1.test
|
| diff --git a/third_party/sqlite/src/test/pager1.test b/third_party/sqlite/src/test/pager1.test
|
| index 8c31e1539c36689863f9d508cf0c6492a07c7a7a..005b356080dd98271b8aaf306ca8bb021d3dc4ed 100644
|
| --- a/third_party/sqlite/src/test/pager1.test
|
| +++ b/third_party/sqlite/src/test/pager1.test
|
| @@ -15,6 +15,7 @@ source $testdir/tester.tcl
|
| source $testdir/lock_common.tcl
|
| source $testdir/malloc_common.tcl
|
| source $testdir/wal_common.tcl
|
| +set testprefix pager1
|
|
|
| # Do not use a codec for tests in this file, as the database file is
|
| # manipulated directly using tcl scripts (using the [hexio_write] command).
|
| @@ -54,6 +55,8 @@ do_not_use_codec
|
| # pager1-16.*: Varying sqlite3_vfs.mxPathname
|
| #
|
| # pager1-17.*: Tests related to "PRAGMA omit_readlock"
|
| +# (The omit_readlock pragma has been removed and so have
|
| +# these tests.)
|
| #
|
| # pager1-18.*: Test that the pager layer responds correctly if the b-tree
|
| # requests an invalid page number (due to db corruption).
|
| @@ -268,7 +271,7 @@ do_execsql_test pager1-3.1.2 {
|
| } {3 0}
|
| do_catchsql_test pager1-3.1.3 {
|
| INSERT INTO t1 SELECT a+3, randomblob(1500) FROM t1
|
| -} {1 {constraint failed}}
|
| +} {1 {CHECK constraint failed: counter}}
|
| do_execsql_test pager1-3.4 { SELECT * FROM counter } {3 0}
|
| do_execsql_test pager1-3.5 { SELECT a FROM t1 } {1 2 3}
|
| do_execsql_test pager1-3.6 { COMMIT } {}
|
| @@ -441,6 +444,8 @@ do_test pager1.4.2.1 {
|
| db close
|
| tstvfs delete
|
| } {}
|
| +
|
| +if {$::tcl_platform(platform)!="windows"} {
|
| do_test pager1.4.2.2 {
|
| faultsim_restore_and_reopen
|
| execsql {
|
| @@ -450,7 +455,7 @@ do_test pager1.4.2.2 {
|
| } {4 ok}
|
| do_test pager1.4.2.3 {
|
| faultsim_restore_and_reopen
|
| - foreach f [glob test.db-mj*] { file delete -force $f }
|
| + foreach f [glob test.db-mj*] { forcedelete $f }
|
| execsql {
|
| SELECT count(*) FROM t1;
|
| PRAGMA integrity_check;
|
| @@ -458,7 +463,7 @@ do_test pager1.4.2.3 {
|
| } {64 ok}
|
| do_test pager1.4.2.4 {
|
| faultsim_restore_and_reopen
|
| - hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456
|
| + hexio_write test.db-journal [expr [file size test.db-journal]-30] 123456
|
| execsql {
|
| SELECT count(*) FROM t1;
|
| PRAGMA integrity_check;
|
| @@ -466,13 +471,14 @@ do_test pager1.4.2.4 {
|
| } {4 ok}
|
| do_test pager1.4.2.5 {
|
| faultsim_restore_and_reopen
|
| - hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456
|
| - foreach f [glob test.db-mj*] { file delete -force $f }
|
| + hexio_write test.db-journal [expr [file size test.db-journal]-30] 123456
|
| + foreach f [glob test.db-mj*] { forcedelete $f }
|
| execsql {
|
| SELECT count(*) FROM t1;
|
| PRAGMA integrity_check;
|
| }
|
| } {4 ok}
|
| +}
|
|
|
| do_test pager1.4.3.1 {
|
| testvfs tstvfs -default 1
|
| @@ -519,18 +525,27 @@ db close
|
| # file-system is saved just before the xDelete() call to remove the
|
| # master journal file from the file-system.
|
| #
|
| +set pwd [get_pwd]
|
| testvfs tv -default 1
|
| tv script copy_on_mj_delete
|
| set ::mj_filename_length 0
|
| proc copy_on_mj_delete {method filename args} {
|
| if {[string match *mj* [file tail $filename]]} {
|
| - set ::mj_filename_length [string length $filename]
|
| + #
|
| + # NOTE: Is the file name relative? If so, add the length of the current
|
| + # directory.
|
| + #
|
| + if {[is_relative_file $filename]} {
|
| + set ::mj_filename_length \
|
| + [expr {[string length $filename] + [string length $::pwd]}]
|
| + } else {
|
| + set ::mj_filename_length [string length $filename]
|
| + }
|
| faultsim_save
|
| }
|
| return SQLITE_OK
|
| }
|
|
|
| -set pwd [pwd]
|
| foreach {tn1 tcl} {
|
| 1 { set prefix "test.db" }
|
| 2 {
|
| @@ -646,7 +661,7 @@ foreach {tn1 tcl} {
|
| #
|
| do_test pager1-4.4.$tn.7 {
|
| faultsim_restore_and_reopen $prefix
|
| - foreach f [glob ${prefix}-mj*] { file delete -force $f }
|
| + foreach f [glob ${prefix}-mj*] { forcedelete $f }
|
| execsql "ATTACH '${prefix}2' AS aux"
|
| } {}
|
| do_execsql_test pager1-4.4.$tn.8 {
|
| @@ -661,7 +676,7 @@ foreach {tn1 tcl} {
|
| }
|
| db close
|
| tv delete
|
| -file delete -force $dirname
|
| +forcedelete $dirname
|
|
|
|
|
| # Set up a VFS to make a copy of the file-system just before deleting a
|
| @@ -738,7 +753,7 @@ sqlite3 db test.db -readonly 1
|
| do_catchsql_test pager1.4.5.6 {
|
| SELECT * FROM t1;
|
| SELECT * FROM t2;
|
| -} {1 {disk I/O error}}
|
| +} {1 {attempt to write a readonly database}}
|
| db close
|
|
|
| # Snapshot the file-system just before multi-file commit. Save the name
|
| @@ -869,19 +884,45 @@ do_execsql_test pager1.4.7.1 {
|
| tv filter {}
|
| db close
|
| tv delete
|
| +catch {
|
| + test_syscall install fchmod
|
| + test_syscall fault 1 1
|
| +}
|
| do_test pager1.4.7.2 {
|
| faultsim_restore_and_reopen
|
| catch {file attributes test.db-journal -permissions r--------}
|
| catch {file attributes test.db-journal -readonly 1}
|
| catchsql { SELECT * FROM t1 }
|
| } {1 {unable to open database file}}
|
| +catch {
|
| + test_syscall reset
|
| + test_syscall fault 0 0
|
| +}
|
| do_test pager1.4.7.3 {
|
| db close
|
| catch {file attributes test.db-journal -permissions rw-rw-rw-}
|
| catch {file attributes test.db-journal -readonly 0}
|
| - file delete test.db-journal
|
| + delete_file test.db-journal
|
| file exists test.db-journal
|
| } {0}
|
| +do_test pager1.4.8.1 {
|
| + catch {file attributes test.db -permissions r--------}
|
| + catch {file attributes test.db -readonly 1}
|
| + sqlite3 db test.db
|
| + db eval { SELECT * FROM t1 }
|
| + sqlite3_db_readonly db main
|
| +} {1}
|
| +do_test pager1.4.8.2 {
|
| + sqlite3_db_readonly db xyz
|
| +} {-1}
|
| +do_test pager1.4.8.3 {
|
| + db close
|
| + catch {file attributes test.db -readonly 0}
|
| + catch {file attributes test.db -permissions rw-rw-rw-} msg
|
| + sqlite3 db test.db
|
| + db eval { SELECT * FROM t1 }
|
| + sqlite3_db_readonly db main
|
| +} {0}
|
|
|
| #-------------------------------------------------------------------------
|
| # The following tests deal with multi-file commits.
|
| @@ -987,8 +1028,28 @@ do_test pager1-5.4.1 {
|
| INSERT INTO t2 VALUES(85, 'Gorbachev');
|
| COMMIT;
|
| }
|
| - set ::max_journal
|
| -} [expr 2615+[string length [pwd]]]
|
| +
|
| + # The size of the journal file is now:
|
| + #
|
| + # 1) 512 byte header +
|
| + # 2) 2 * (1024+8) byte records +
|
| + # 3) 20+N bytes of master-journal pointer, where N is the size of
|
| + # the master-journal name encoded as utf-8 with no nul term.
|
| + #
|
| + set mj_pointer [expr {
|
| + 20 + [string length "test.db-mjXXXXXX9XX"]
|
| + }]
|
| + #
|
| + # NOTE: For item 3 above, if the current SQLite VFS lacks the concept of a
|
| + # current directory, the length of the current directory name plus 1
|
| + # character for the directory separator character are NOT counted as
|
| + # part of the total size; otherwise, they are.
|
| + #
|
| + ifcapable curdir {
|
| + set mj_pointer [expr {$mj_pointer + [string length [get_pwd]] + 1}]
|
| + }
|
| + expr {$::max_journal==(512+2*(1024+8)+$mj_pointer)}
|
| +} 1
|
| do_test pager1-5.4.2 {
|
| set ::max_journal 0
|
| execsql {
|
| @@ -998,8 +1059,25 @@ do_test pager1-5.4.2 {
|
| DELETE FROM t2 WHERE b = 'Lenin';
|
| COMMIT;
|
| }
|
| - set ::max_journal
|
| -} [expr 3111+[string length [pwd]]]
|
| +
|
| + # In synchronous=full mode, the master-journal pointer is not written
|
| + # directly after the last record in the journal file. Instead, it is
|
| + # written starting at the next (in this case 512 byte) sector boundary.
|
| + #
|
| + set mj_pointer [expr {
|
| + 20 + [string length "test.db-mjXXXXXX9XX"]
|
| + }]
|
| + #
|
| + # NOTE: If the current SQLite VFS lacks the concept of a current directory,
|
| + # the length of the current directory name plus 1 character for the
|
| + # directory separator character are NOT counted as part of the total
|
| + # size; otherwise, they are.
|
| + #
|
| + ifcapable curdir {
|
| + set mj_pointer [expr {$mj_pointer + [string length [get_pwd]] + 1}]
|
| + }
|
| + expr {$::max_journal==(((512+2*(1024+8)+511)/512)*512 + $mj_pointer)}
|
| +} 1
|
| db close
|
| tv delete
|
|
|
| @@ -1296,7 +1374,7 @@ do_test pager1-9.4.1 {
|
| } {SQLITE_DONE SQLITE_OK}
|
| do_test pager1-9.4.2 {
|
| list [file size test.db2] [file size test.db]
|
| -} {0 0}
|
| +} {1024 0}
|
| db2 close
|
|
|
| #-------------------------------------------------------------------------
|
| @@ -1305,10 +1383,12 @@ db2 close
|
| #
|
| testvfs tv -default 1
|
| foreach sectorsize {
|
| + 16
|
| 32 64 128 256 512 1024 2048
|
| 4096 8192 16384 32768 65536 131072 262144
|
| } {
|
| tv sectorsize $sectorsize
|
| + tv devchar {}
|
| set eff $sectorsize
|
| if {$sectorsize < 512} { set eff 512 }
|
| if {$sectorsize > 65536} { set eff 65536 }
|
| @@ -1326,7 +1406,7 @@ foreach sectorsize {
|
| COMMIT;
|
| }
|
| file size test.db-journal
|
| - } [expr $sectorsize > 65536 ? 65536 : $sectorsize]
|
| + } [expr $sectorsize > 65536 ? 65536 : ($sectorsize<32 ? 512 : $sectorsize)]
|
|
|
| do_test pager1-10.$sectorsize.2 {
|
| execsql {
|
| @@ -1548,6 +1628,7 @@ do_execsql_test pager1-13.1.1 {
|
| UPDATE t1 SET b = a_string(400);
|
| } {persist}
|
|
|
| +if {$::tcl_platform(platform)!="windows"} {
|
| # Run transactions of increasing sizes. Eventually, one (or more than one)
|
| # of these will write just enough content that one of the old headers created
|
| # by the transaction in the block above lies immediately after the content
|
| @@ -1570,7 +1651,9 @@ for {set nUp 1} {$nUp<64} {incr nUp} {
|
| } {ok}
|
| db2 close
|
| }
|
| +}
|
|
|
| +if {$::tcl_platform(platform)!="windows"} {
|
| # Same test as above. But this time with an index on the table.
|
| #
|
| do_execsql_test pager1-13.2.1 {
|
| @@ -1591,6 +1674,7 @@ for {set nUp 1} {$nUp<64} {incr nUp} {
|
| } {ok}
|
| db2 close
|
| }
|
| +}
|
|
|
| db close
|
| tv delete
|
| @@ -1619,7 +1703,7 @@ do_catchsql_test pager1-14.1.4 {
|
| BEGIN;
|
| INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1;
|
| INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1;
|
| -} {1 {PRIMARY KEY must be unique}}
|
| +} {1 {UNIQUE constraint failed: t1.rowid}}
|
| do_execsql_test pager1-14.1.5 {
|
| COMMIT;
|
| SELECT * FROM t1;
|
| @@ -1653,7 +1737,7 @@ for {set i 0} {$i<513} {incr i 3} {
|
| testvfs tv -default 1
|
| tv script xOpenCb
|
| tv filter xOpen
|
| -proc xOpenCb {method filename} {
|
| +proc xOpenCb {method filename args} {
|
| set ::file_len [string length $filename]
|
| }
|
| sqlite3 db test.db
|
| @@ -1681,75 +1765,6 @@ for {set ii [expr $::file_len-5]} {$ii < [expr $::file_len+20]} {incr ii} {
|
| tv delete
|
| }
|
|
|
| -#-------------------------------------------------------------------------
|
| -# Test "PRAGMA omit_readlock".
|
| -#
|
| -# pager1-17.$tn.1.*: Test that if a second connection has an open
|
| -# read-transaction, it is not usually possible to write
|
| -# the database.
|
| -#
|
| -# pager1-17.$tn.2.*: Test that if the second connection was opened with
|
| -# the SQLITE_OPEN_READONLY flag, and
|
| -# "PRAGMA omit_readlock = 1" is executed before attaching
|
| -# the database and opening a read-transaction on it, it is
|
| -# possible to write the db.
|
| -#
|
| -# pager1-17.$tn.3.*: Test that if the second connection was *not* opened with
|
| -# the SQLITE_OPEN_READONLY flag, executing
|
| -# "PRAGMA omit_readlock = 1" has no effect.
|
| -#
|
| -do_multiclient_test tn {
|
| - do_test pager1-17.$tn.1.1 {
|
| - sql1 {
|
| - CREATE TABLE t1(a, b);
|
| - INSERT INTO t1 VALUES(1, 2);
|
| - }
|
| - sql2 {
|
| - BEGIN;
|
| - SELECT * FROM t1;
|
| - }
|
| - } {1 2}
|
| - do_test pager1-17.$tn.1.2 {
|
| - csql1 { INSERT INTO t1 VALUES(3, 4) }
|
| - } {1 {database is locked}}
|
| - do_test pager1-17.$tn.1.3 {
|
| - sql2 { COMMIT }
|
| - sql1 { INSERT INTO t1 VALUES(3, 4) }
|
| - } {}
|
| -
|
| - do_test pager1-17.$tn.2.1 {
|
| - code2 {
|
| - db2 close
|
| - sqlite3 db2 :memory: -readonly 1
|
| - }
|
| - sql2 {
|
| - PRAGMA omit_readlock = 1;
|
| - ATTACH 'test.db' AS two;
|
| - BEGIN;
|
| - SELECT * FROM t1;
|
| - }
|
| - } {1 2 3 4}
|
| - do_test pager1-17.$tn.2.2 { sql1 "INSERT INTO t1 VALUES(5, 6)" } {}
|
| - do_test pager1-17.$tn.2.3 { sql2 "SELECT * FROM t1" } {1 2 3 4}
|
| - do_test pager1-17.$tn.2.4 { sql2 "COMMIT ; SELECT * FROM t1" } {1 2 3 4 5 6}
|
| -
|
| - do_test pager1-17.$tn.3.1 {
|
| - code2 {
|
| - db2 close
|
| - sqlite3 db2 :memory:
|
| - }
|
| - sql2 {
|
| - PRAGMA omit_readlock = 1;
|
| - ATTACH 'test.db' AS two;
|
| - BEGIN;
|
| - SELECT * FROM t1;
|
| - }
|
| - } {1 2 3 4 5 6}
|
| - do_test pager1-17.$tn.3.2 {
|
| - csql1 { INSERT INTO t1 VALUES(3, 4) }
|
| - } {1 {database is locked}}
|
| - do_test pager1-17.$tn.3.3 { sql2 COMMIT } {}
|
| -}
|
|
|
| #-------------------------------------------------------------------------
|
| # Test the pagers response to the b-tree layer requesting illegal page
|
| @@ -1759,6 +1774,10 @@ do_multiclient_test tn {
|
| # + Page 0,
|
| # + A page with a page number greater than (2^31-1).
|
| #
|
| +# These tests will not work if SQLITE_DIRECT_OVERFLOW_READ is defined. In
|
| +# that case IO errors are sometimes reported instead of SQLITE_CORRUPT.
|
| +#
|
| +ifcapable !direct_read {
|
| do_test pager1-18.1 {
|
| faultsim_delete_and_reopen
|
| db func a_string a_string
|
| @@ -1786,7 +1805,7 @@ do_test pager1-18.2 {
|
| catchsql { SELECT count(*) FROM t1 } db2
|
| } {1 {database disk image is malformed}}
|
| db2 close
|
| -do_test pager1-18.3 {
|
| +do_test pager1-18.3.1 {
|
| execsql {
|
| CREATE TABLE t2(x);
|
| INSERT INTO t2 VALUES(a_string(5000));
|
| @@ -1794,13 +1813,38 @@ do_test pager1-18.3 {
|
| set pgno [expr ([file size test.db] / 1024)-2]
|
| hexio_write test.db [expr ($pgno-1)*1024] 00000000
|
| sqlite3 db2 test.db
|
| - catchsql { SELECT length(x) FROM t2 } db2
|
| + # even though x is malformed, because typeof() does
|
| + # not load the content of x, the error is not noticed.
|
| + catchsql { SELECT typeof(x) FROM t2 } db2
|
| +} {0 text}
|
| +do_test pager1-18.3.2 {
|
| + # in this case, the value of x is loaded and so the error is
|
| + # detected
|
| + catchsql { SELECT length(x||'') FROM t2 } db2
|
| +} {1 {database disk image is malformed}}
|
| +db2 close
|
| +do_test pager1-18.3.3 {
|
| + execsql {
|
| + DELETE FROM t2;
|
| + INSERT INTO t2 VALUES(randomblob(5000));
|
| + }
|
| + set pgno [expr ([file size test.db] / 1024)-2]
|
| + hexio_write test.db [expr ($pgno-1)*1024] 00000000
|
| + sqlite3 db2 test.db
|
| + # even though x is malformed, because length() and typeof() do
|
| + # not load the content of x, the error is not noticed.
|
| + catchsql { SELECT length(x), typeof(x) FROM t2 } db2
|
| +} {0 {5000 blob}}
|
| +do_test pager1-18.3.4 {
|
| + # in this case, the value of x is loaded and so the error is
|
| + # detected
|
| + catchsql { SELECT length(x||'') FROM t2 } db2
|
| } {1 {database disk image is malformed}}
|
| db2 close
|
| do_test pager1-18.4 {
|
| hexio_write test.db [expr ($pgno-1)*1024] 90000000
|
| sqlite3 db2 test.db
|
| - catchsql { SELECT length(x) FROM t2 } db2
|
| + catchsql { SELECT length(x||'') FROM t2 } db2
|
| } {1 {database disk image is malformed}}
|
| db2 close
|
| do_test pager1-18.5 {
|
| @@ -1834,6 +1878,7 @@ do_test pager1-18.6 {
|
| sqlite3 db test.db
|
| catchsql { SELECT length(x) FROM t1 }
|
| } {1 {database disk image is malformed}}
|
| +}
|
|
|
| do_test pager1-19.1 {
|
| sqlite3 db ""
|
| @@ -1985,31 +2030,33 @@ ifcapable wal {
|
| # pager1-22.1.*: is a no-op on a non-WAL db, and
|
| # pager1-22.2.*: does not cause xSync calls with a synchronous=off db.
|
| #
|
| -do_test pager1-22.1.1 {
|
| - faultsim_delete_and_reopen
|
| - execsql {
|
| - CREATE TABLE ko(c DEFAULT 'abc', b DEFAULT 'def');
|
| - INSERT INTO ko DEFAULT VALUES;
|
| - }
|
| - execsql { PRAGMA wal_checkpoint }
|
| -} {0 -1 -1}
|
| -do_test pager1-22.2.1 {
|
| - testvfs tv -default 1
|
| - tv filter xSync
|
| - tv script xSyncCb
|
| - proc xSyncCb {args} {incr ::synccount}
|
| - set ::synccount 0
|
| - sqlite3 db test.db
|
| - execsql {
|
| - PRAGMA synchronous = off;
|
| - PRAGMA journal_mode = WAL;
|
| - INSERT INTO ko DEFAULT VALUES;
|
| - }
|
| - execsql { PRAGMA wal_checkpoint }
|
| - set synccount
|
| -} {0}
|
| -db close
|
| -tv delete
|
| +ifcapable wal {
|
| + do_test pager1-22.1.1 {
|
| + faultsim_delete_and_reopen
|
| + execsql {
|
| + CREATE TABLE ko(c DEFAULT 'abc', b DEFAULT 'def');
|
| + INSERT INTO ko DEFAULT VALUES;
|
| + }
|
| + execsql { PRAGMA wal_checkpoint }
|
| + } {0 -1 -1}
|
| + do_test pager1-22.2.1 {
|
| + testvfs tv -default 1
|
| + tv filter xSync
|
| + tv script xSyncCb
|
| + proc xSyncCb {args} {incr ::synccount}
|
| + set ::synccount 0
|
| + sqlite3 db test.db
|
| + execsql {
|
| + PRAGMA synchronous = off;
|
| + PRAGMA journal_mode = WAL;
|
| + INSERT INTO ko DEFAULT VALUES;
|
| + }
|
| + execsql { PRAGMA wal_checkpoint }
|
| + set synccount
|
| + } {0}
|
| + db close
|
| + tv delete
|
| +}
|
|
|
| #-------------------------------------------------------------------------
|
| # Tests for changing journal mode.
|
| @@ -2198,7 +2245,6 @@ do_test pager1-25-1 {
|
| }
|
| db close
|
| } {}
|
| -breakpoint
|
| do_test pager1-25-2 {
|
| faultsim_delete_and_reopen
|
| execsql {
|
| @@ -2361,8 +2407,8 @@ do_test pager1-29.2 {
|
| #
|
| do_test pager1-30.1 {
|
| db close
|
| - file delete test.db
|
| - file delete test.db-journal
|
| + delete_file test.db
|
| + delete_file test.db-journal
|
| set fd [open test.db-journal w]
|
| seek $fd [expr 512+1032*2]
|
| puts -nonewline $fd x
|
| @@ -2381,6 +2427,7 @@ do_test pager1-30.1 {
|
| # file can still be rolled back. This is required for backward compatibility -
|
| # versions of SQLite prior to 3.5.8 always set this field to zero.
|
| #
|
| +if {$tcl_platform(platform)=="unix"} {
|
| do_test pager1-31.1 {
|
| faultsim_delete_and_reopen
|
| execsql {
|
| @@ -2401,14 +2448,370 @@ do_test pager1-31.1 {
|
| BEGIN;
|
| UPDATE t1 SET y = randomblob(1499);
|
| }
|
| - file copy test.db test.db2
|
| - file copy test.db-journal test.db2-journal
|
| + copy_file test.db test.db2
|
| + copy_file test.db-journal test.db2-journal
|
|
|
| hexio_write test.db2-journal 24 00000000
|
| sqlite3 db2 test.db2
|
| execsql { PRAGMA integrity_check } db2
|
| } {ok}
|
| +}
|
| +
|
| +#-------------------------------------------------------------------------
|
| +# Test that a database file can be "pre-hinted" to a certain size and that
|
| +# subsequent spilling of the pager cache does not result in the database
|
| +# file being shrunk.
|
| +#
|
| +catch {db close}
|
| +forcedelete test.db
|
| +
|
| +do_test pager1-32.1 {
|
| + sqlite3 db test.db
|
| + execsql {
|
| + CREATE TABLE t1(x, y);
|
| + }
|
| + db close
|
| + sqlite3 db test.db
|
| + execsql {
|
| + BEGIN;
|
| + INSERT INTO t1 VALUES(1, randomblob(10000));
|
| + }
|
| + file_control_chunksize_test db main 1024
|
| + file_control_sizehint_test db main 20971520; # 20MB
|
| + execsql {
|
| + PRAGMA cache_size = 10;
|
| + INSERT INTO t1 VALUES(1, randomblob(10000));
|
| + INSERT INTO t1 VALUES(2, randomblob(10000));
|
| + INSERT INTO t1 SELECT x+2, randomblob(10000) from t1;
|
| + INSERT INTO t1 SELECT x+4, randomblob(10000) from t1;
|
| + INSERT INTO t1 SELECT x+8, randomblob(10000) from t1;
|
| + INSERT INTO t1 SELECT x+16, randomblob(10000) from t1;
|
| + SELECT count(*) FROM t1;
|
| + COMMIT;
|
| + }
|
| + db close
|
| + file size test.db
|
| +} {20971520}
|
| +
|
| +# Cleanup 20MB file left by the previous test.
|
| +forcedelete test.db
|
| +
|
| +#-------------------------------------------------------------------------
|
| +# Test that if a transaction is committed in journal_mode=DELETE mode,
|
| +# and the call to unlink() returns an ENOENT error, the COMMIT does not
|
| +# succeed.
|
| +#
|
| +if {$::tcl_platform(platform)=="unix"} {
|
| + do_test pager1-33.1 {
|
| + sqlite3 db test.db
|
| + execsql {
|
| + CREATE TABLE t1(x);
|
| + INSERT INTO t1 VALUES('one');
|
| + INSERT INTO t1 VALUES('two');
|
| + BEGIN;
|
| + INSERT INTO t1 VALUES('three');
|
| + INSERT INTO t1 VALUES('four');
|
| + }
|
| + forcedelete bak-journal
|
| + file rename test.db-journal bak-journal
|
| +
|
| + catchsql COMMIT
|
| + } {1 {disk I/O error}}
|
| +
|
| + do_test pager1-33.2 {
|
| + file rename bak-journal test.db-journal
|
| + execsql { SELECT * FROM t1 }
|
| + } {one two}
|
| +}
|
| +
|
| +#-------------------------------------------------------------------------
|
| +# Test that appending pages to the database file then moving those pages
|
| +# to the free-list before the transaction is committed does not cause
|
| +# an error.
|
| +#
|
| +foreach {tn pragma strsize} {
|
| + 1 { PRAGMA mmap_size = 0 } 2400
|
| + 2 { } 2400
|
| + 3 { PRAGMA mmap_size = 0 } 4400
|
| + 4 { } 4400
|
| +} {
|
| + reset_db
|
| + db func a_string a_string
|
| + db eval $pragma
|
| + do_execsql_test 34.$tn.1 {
|
| + CREATE TABLE t1(a, b);
|
| + INSERT INTO t1 VALUES(1, 2);
|
| + }
|
| + do_execsql_test 34.$tn.2 {
|
| + BEGIN;
|
| + INSERT INTO t1 VALUES(2, a_string($strsize));
|
| + DELETE FROM t1 WHERE oid=2;
|
| + COMMIT;
|
| + PRAGMA integrity_check;
|
| + } {ok}
|
| +}
|
| +
|
| +#-------------------------------------------------------------------------
|
| +#
|
| +reset_db
|
| +do_test 35 {
|
| + sqlite3 db test.db
|
| +
|
| + execsql {
|
| + CREATE TABLE t1(x, y);
|
| + PRAGMA journal_mode = WAL;
|
| + INSERT INTO t1 VALUES(1, 2);
|
| + }
|
| +
|
| + execsql {
|
| + BEGIN;
|
| + CREATE TABLE t2(a, b);
|
| + }
|
| +
|
| + hexio_write test.db-shm [expr 16*1024] [string repeat 0055 8192]
|
| + catchsql ROLLBACK
|
| +} {0 {}}
|
| +
|
| +do_multiclient_test tn {
|
| + sql1 {
|
| + PRAGMA auto_vacuum = 0;
|
| + CREATE TABLE t1(x, y);
|
| + INSERT INTO t1 VALUES(1, 2);
|
| + }
|
| +
|
| + do_test 36.$tn.1 {
|
| + sql2 { PRAGMA max_page_count = 2 }
|
| + list [catch { sql2 { CREATE TABLE t2(x) } } msg] $msg
|
| + } {1 {database or disk is full}}
|
| +
|
| + sql1 { PRAGMA checkpoint_fullfsync = 1 }
|
| + sql1 { CREATE TABLE t2(x) }
|
| +
|
| + do_test 36.$tn.2 {
|
| + sql2 { INSERT INTO t2 VALUES('xyz') }
|
| + list [catch { sql2 { CREATE TABLE t3(x) } } msg] $msg
|
| + } {1 {database or disk is full}}
|
| +}
|
| +
|
| +forcedelete test1 test2
|
| +foreach {tn uri} {
|
| + 1 {file:?mode=memory&cache=shared}
|
| + 2 {file:one?mode=memory&cache=shared}
|
| + 3 {file:test1?cache=shared}
|
| + 4 {file:test2?another=parameter&yet=anotherone}
|
| +} {
|
| + do_test 37.$tn {
|
| + catch { db close }
|
| + sqlite3_shutdown
|
| + sqlite3_config_uri 1
|
| + sqlite3 db $uri
|
| +
|
| + db eval {
|
| + CREATE TABLE t1(x);
|
| + INSERT INTO t1 VALUES(1);
|
| + SELECT * FROM t1;
|
| + }
|
| + } {1}
|
| +
|
| + do_execsql_test 37.$tn.2 {
|
| + VACUUM;
|
| + SELECT * FROM t1;
|
| + } {1}
|
| +
|
| + db close
|
| + sqlite3_shutdown
|
| + sqlite3_config_uri 0
|
| +}
|
| +
|
| +do_test 38.1 {
|
| + catch { db close }
|
| + forcedelete test.db
|
| + set fd [open test.db w]
|
| + puts $fd "hello world"
|
| + close $fd
|
| + sqlite3 db test.db
|
| + catchsql { CREATE TABLE t1(x) }
|
| +} {1 {file is encrypted or is not a database}}
|
| +do_test 38.2 {
|
| + catch { db close }
|
| + forcedelete test.db
|
| +} {}
|
| +
|
| +do_test 39.1 {
|
| + sqlite3 db test.db
|
| + execsql {
|
| + PRAGMA auto_vacuum = 1;
|
| + CREATE TABLE t1(x);
|
| + INSERT INTO t1 VALUES('xxx');
|
| + INSERT INTO t1 VALUES('two');
|
| + INSERT INTO t1 VALUES(randomblob(400));
|
| + INSERT INTO t1 VALUES(randomblob(400));
|
| + INSERT INTO t1 VALUES(randomblob(400));
|
| + INSERT INTO t1 VALUES(randomblob(400));
|
| + BEGIN;
|
| + UPDATE t1 SET x = 'one' WHERE rowid=1;
|
| + }
|
| + set ::stmt [sqlite3_prepare db "SELECT * FROM t1 ORDER BY rowid" -1 dummy]
|
| + sqlite3_step $::stmt
|
| + sqlite3_column_text $::stmt 0
|
| +} {one}
|
| +do_test 39.2 {
|
| + execsql { CREATE TABLE t2(x) }
|
| + sqlite3_step $::stmt
|
| + sqlite3_column_text $::stmt 0
|
| +} {two}
|
| +do_test 39.3 {
|
| + sqlite3_finalize $::stmt
|
| + execsql COMMIT
|
| +} {}
|
| +
|
| +do_execsql_test 39.4 {
|
| + PRAGMA auto_vacuum = 2;
|
| + CREATE TABLE t3(x);
|
| + CREATE TABLE t4(x);
|
| +
|
| + DROP TABLE t2;
|
| + DROP TABLE t3;
|
| + DROP TABLE t4;
|
| +}
|
| +do_test 39.5 {
|
| + db close
|
| + sqlite3 db test.db
|
| + execsql {
|
| + PRAGMA cache_size = 1;
|
| + PRAGMA incremental_vacuum;
|
| + PRAGMA integrity_check;
|
| + }
|
| +} {ok}
|
| +
|
| +do_test 40.1 {
|
| + reset_db
|
| + execsql {
|
| + PRAGMA auto_vacuum = 1;
|
| + CREATE TABLE t1(x PRIMARY KEY);
|
| + INSERT INTO t1 VALUES(randomblob(1200));
|
| + PRAGMA page_count;
|
| + }
|
| +} {6}
|
| +do_test 40.2 {
|
| + execsql {
|
| + INSERT INTO t1 VALUES(randomblob(1200));
|
| + INSERT INTO t1 VALUES(randomblob(1200));
|
| + INSERT INTO t1 VALUES(randomblob(1200));
|
| + }
|
| +} {}
|
| +do_test 40.3 {
|
| + db close
|
| + sqlite3 db test.db
|
| + execsql {
|
| + PRAGMA cache_size = 1;
|
| + CREATE TABLE t2(x);
|
| + PRAGMA integrity_check;
|
| + }
|
| +} {ok}
|
| +
|
| +do_test 41.1 {
|
| + reset_db
|
| + execsql {
|
| + CREATE TABLE t1(x PRIMARY KEY);
|
| + INSERT INTO t1 VALUES(randomblob(200));
|
| + INSERT INTO t1 SELECT randomblob(200) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(200) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(200) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(200) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(200) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(200) FROM t1;
|
| + }
|
| +} {}
|
| +do_test 41.2 {
|
| + testvfs tv -default 1
|
| + tv sectorsize 16384;
|
| + tv devchar [list]
|
| + db close
|
| + sqlite3 db test.db
|
| + execsql {
|
| + PRAGMA cache_size = 1;
|
| + DELETE FROM t1 WHERE rowid%4;
|
| + PRAGMA integrity_check;
|
| + }
|
| +} {ok}
|
| +db close
|
| +tv delete
|
| +
|
| +set pending_prev [sqlite3_test_control_pending_byte 0x1000000]
|
| +do_test 42.1 {
|
| + reset_db
|
| + execsql {
|
| + CREATE TABLE t1(x, y);
|
| + INSERT INTO t1 VALUES(randomblob(200), randomblob(200));
|
| + INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
|
| + }
|
| + db close
|
| + sqlite3_test_control_pending_byte 0x0010000
|
| + sqlite3 db test.db
|
| + db eval { PRAGMA mmap_size = 0 }
|
| + catchsql { SELECT sum(length(y)) FROM t1 }
|
| +} {1 {database disk image is malformed}}
|
| +do_test 42.2 {
|
| + reset_db
|
| + execsql {
|
| + CREATE TABLE t1(x, y);
|
| + INSERT INTO t1 VALUES(randomblob(200), randomblob(200));
|
| + INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
|
| + INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1;
|
| + }
|
| + db close
|
| +
|
| + testvfs tv -default 1
|
| + tv sectorsize 16384;
|
| + tv devchar [list]
|
| + sqlite3 db test.db -vfs tv
|
| + execsql { UPDATE t1 SET x = randomblob(200) }
|
| +} {}
|
| +db close
|
| +tv delete
|
| +sqlite3_test_control_pending_byte $pending_prev
|
| +
|
| +do_test 43.1 {
|
| + reset_db
|
| + execsql {
|
| + CREATE TABLE t1(x, y);
|
| + INSERT INTO t1 VALUES(1, 2);
|
| + CREATE TABLE t2(x, y);
|
| + INSERT INTO t2 VALUES(1, 2);
|
| + CREATE TABLE t3(x, y);
|
| + INSERT INTO t3 VALUES(1, 2);
|
| + }
|
| + db close
|
| + sqlite3 db test.db
|
| +
|
| + db eval { PRAGMA mmap_size = 0 }
|
| + db eval { SELECT * FROM t1 }
|
| + sqlite3_db_status db CACHE_MISS 0
|
| +} {0 2 0}
|
|
|
| +do_test 43.2 {
|
| + db eval { SELECT * FROM t2 }
|
| + sqlite3_db_status db CACHE_MISS 1
|
| +} {0 3 0}
|
|
|
| +do_test 43.3 {
|
| + db eval { SELECT * FROM t3 }
|
| + sqlite3_db_status db CACHE_MISS 0
|
| +} {0 1 0}
|
|
|
| finish_test
|
|
|