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 |