#
# pager1-10.*: Test that the assumed file-system sector-size is limited to
# 64KB.
-#
+#
+# pager1-12.*: Tests involving "PRAGMA page_size"
+#
+# pager1-13.*: Cases specific to "PRAGMA journal_mode=PERSIST"
+#
+# pager1-14.*: Cases specific to "PRAGMA journal_mode=OFF"
#
set a_string_counter 1
sql1 {
CREATE TABLE t1(a PRIMARY KEY, b);
CREATE INDEX i1 ON t1(b);
- INSERT INTO t1 VALUES(1, 'one');
- INSERT INTO t1 VALUES(2, 'two');
+ INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two');
}
} {}
do_test pager1-$tn.2 { sql2 { SELECT * FROM t1 } } {1 one 2 two}
do_test pager1-$tn.27 { sql1 { SELECT * FROM t1 } } {21 one 22 two 23 three}
do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {21 one 22 two 23 three}
do_test pager1-$tn.28 { sql3 { SELECT * FROM t1 } } {21 one 22 two 23 three}
+
+ # Install a busy-handler for connection [db].
+ #
+ set ::nbusy [list]
+ proc busy {n} {
+ lappend ::nbusy $n
+ if {$n>5} { sql2 COMMIT }
+ return 0
+ }
+ db busy busy
+
+ do_test pager1-$tn.29 {
+ sql1 { BEGIN ; INSERT INTO t1 VALUES('x', 'y') }
+ } {}
+ do_test pager1-$tn.30 {
+ sql2 { BEGIN ; SELECT * FROM t1 }
+ } {21 one 22 two 23 three}
+ do_test pager1-$tn.31 { sql1 COMMIT } {}
+ do_test pager1-$tn.32 { set ::nbusy } {0 1 2 3 4 5 6}
}
#-------------------------------------------------------------------------
} {0 0}
do_execsql_test pager1-3.1.2 {
+ PRAGMA cache_size = 10;
BEGIN;
INSERT INTO t1 VALUES(1, randomblob(1500));
INSERT INTO t1 VALUES(2, randomblob(1500));
do_execsql_test pager1-3.6 { COMMIT } {}
foreach {tn sql tcl} {
- 9 { PRAGMA synchronous = NORMAL } { }
-
- 7 { PRAGMA synchronous = NORMAL } {
+ 7 { PRAGMA synchronous = NORMAL ; PRAGMA temp_store = 0 } {
testvfs tv -default 1
tv devchar safe_append
}
- 8 { PRAGMA synchronous = FULL } { }
- 10 { PRAGMA synchronous = OFF } { }
- 11 { PRAGMA synchronous = FULL ; PRAGMA fullfsync = 1 } { }
+ 8 { PRAGMA synchronous = NORMAL ; PRAGMA temp_store = 2 } {
+ testvfs tv -default 1
+ tv devchar sequential
+ }
+ 9 { PRAGMA synchronous = FULL } { }
+ 10 { PRAGMA synchronous = NORMAL } { }
+ 11 { PRAGMA synchronous = OFF } { }
+ 12 { PRAGMA synchronous = FULL ; PRAGMA fullfsync = 1 } { }
+ 13 { PRAGMA synchronous = FULL } {
+ testvfs tv -default 1
+ tv devchar sequential
+ }
} {
do_test pager1-3.$tn.1 {
eval $tcl
CREATE TABLE t10(a, b);
}
} {10}
-do_test pager1-6.2 {
- catchsql {
- CREATE TABLE t11(a, b);
- }
+do_catchsql_test pager1-6.2 {
+ CREATE TABLE t11(a, b)
} {1 {database or disk is full}}
+do_execsql_test pager1-6.4 { PRAGMA max_page_count } {10}
+do_execsql_test pager1-6.5 { PRAGMA max_page_count = 15 } {15}
+do_execsql_test pager1-6.6 { CREATE TABLE t11(a, b) } {}
+do_execsql_test pager1-6.7 {
+ BEGIN;
+ INSERT INTO t11 VALUES(1, 2);
+ PRAGMA max_page_count = 13;
+} {13}
+do_execsql_test pager1-6.8 {
+ INSERT INTO t11 VALUES(3, 4);
+ PRAGMA max_page_count = 10;
+} {11}
+do_execsql_test pager1-6.9 { COMMIT } {}
#-------------------------------------------------------------------------
}
}
+#-------------------------------------------------------------------------
+# The following tests, pager1-8.*, test that the special filenames
+# ":memory:" and "" open temporary databases.
+#
foreach {tn filename} {
1 :memory:
2 ""
db2 close
file size test.db-journal
} {0}
-breakpoint
do_execsql_test pager1-11.5 { SELECT count(*) FROM zz } {32}
db close
tv delete
db2 close
}
-finish_test
+#-------------------------------------------------------------------------
+# Test specal "PRAGMA journal_mode=PERSIST" test cases.
+#
+# pager1-13.1.*: This tests a special case encountered in persistent
+# journal mode: If the journal associated with a transaction
+# is smaller than the journal file (because a previous
+# transaction left a very large non-hot journal file in the
+# file-system), then SQLite has to be careful that there is
+# not a journal-header left over from a previous transaction
+# immediately following the journal content just written.
+# If there is, and the process crashes so that the journal
+# becomes a hot-journal and must be rolled back by another
+# process, there is a danger that the other process may roll
+# back the aborted transaction, then continue copying data
+# from an older transaction from the remainder of the journal.
+# See the syncJournal() function for details.
+#
+# pager1-13.2.*: Same test as the previous. This time, throw an index into
+# the mix to make the integrity-check more likely to catch
+# errors.
+#
+testvfs tv -default 1
+tv script xSyncCb
+tv filter xSync
+proc xSyncCb {method filename args} {
+ set t [file tail $filename]
+ if {$t == "test.db"} faultsim_save
+ return SQLITE_OK
+}
+faultsim_delete_and_reopen
+db func a_string a_string
+# The UPDATE statement at the end of this test case creates a really big
+# journal. Since the cache-size is only 10 pages, the journal contains
+# frequent journal headers.
+#
+do_execsql_test pager1-13.1.1 {
+ PRAGMA page_size = 1024;
+ PRAGMA journal_mode = PERSIST;
+ PRAGMA cache_size = 10;
+ BEGIN;
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB);
+ INSERT INTO t1 VALUES(NULL, a_string(400));
+ INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 2 */
+ INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 4 */
+ INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 8 */
+ INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 16 */
+ INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 32 */
+ INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 64 */
+ INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 128 */
+ COMMIT;
+ UPDATE t1 SET b = a_string(400);
+} {persist}
+
+# 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
+# journalled by the current transaction.
+#
+for {set nUp 1} {$nUp<64} {incr nUp} {
+ do_execsql_test pager1-13.1.2.$nUp.1 {
+ UPDATE t1 SET b = a_string(399) WHERE a <= $nUp
+ } {}
+ do_execsql_test pager1-13.1.2.$nUp.2 { PRAGMA integrity_check } {ok}
+
+ # Try to access the snapshot of the file-system.
+ #
+ sqlite3 db2 sv_test.db
+ do_test pager1-13.1.2.$nUp.3 {
+ execsql { SELECT sum(length(b)) FROM t1 } db2
+ } [expr {128*400 - ($nUp-1)}]
+ do_test pager1-13.1.2.$nUp.4 {
+ execsql { PRAGMA integrity_check } db2
+ } {ok}
+ db2 close
+}
+
+# Same test as above. But this time with an index on the table.
+#
+do_execsql_test pager1-13.2.1 {
+ CREATE INDEX i1 ON t1(b);
+ UPDATE t1 SET b = a_string(400);
+} {}
+for {set nUp 1} {$nUp<64} {incr nUp} {
+ do_execsql_test pager1-13.2.2.$nUp.1 {
+ UPDATE t1 SET b = a_string(399) WHERE a <= $nUp
+ } {}
+ do_execsql_test pager1-13.2.2.$nUp.2 { PRAGMA integrity_check } {ok}
+ sqlite3 db2 sv_test.db
+ do_test pager1-13.2.2.$nUp.3 {
+ execsql { SELECT sum(length(b)) FROM t1 } db2
+ } [expr {128*400 - ($nUp-1)}]
+ do_test pager1-13.2.2.$nUp.4 {
+ execsql { PRAGMA integrity_check } db2
+ } {ok}
+ db2 close
+}
+
+db close
+tv delete
+
+#-------------------------------------------------------------------------
+# Test specal "PRAGMA journal_mode=OFF" test cases.
+#
+faultsim_delete_and_reopen
+do_execsql_test pager1-14.1.1 {
+ PRAGMA journal_mode = OFF;
+ CREATE TABLE t1(a, b);
+ BEGIN;
+ INSERT INTO t1 VALUES(1, 2);
+ COMMIT;
+ SELECT * FROM t1;
+} {off 1 2}
+do_catchsql_test pager1-14.1.2 {
+ BEGIN;
+ INSERT INTO t1 VALUES(3, 4);
+ ROLLBACK;
+} {0 {}}
+do_execsql_test pager1-14.1.3 {
+ SELECT * FROM t1;
+} {1 2 3 4}
+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}}
+do_execsql_test pager1-14.1.5 {
+ COMMIT;
+ SELECT * FROM t1;
+} {1 2 3 4 2 2 4 4}
+
+finish_test