123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- # 2015 February 16
- #
- # The author disclaims copyright to this source code. In place of
- # a legal notice, here is a blessing:
- #
- # May you do good and not evil.
- # May you find forgiveness for yourself and forgive others.
- # May you share freely, never taking more than you give.
- #
- #***********************************************************************
- #
- source [file join [file dirname [info script]] rbu_common.tcl]
- if_no_rbu_support { finish_test ; return }
- source $testdir/lock_common.tcl
- set ::testprefix rbu12
- set setup_sql {
- DROP TABLE IF EXISTS xx;
- DROP TABLE IF EXISTS xy;
- CREATE TABLE xx(a, b, c PRIMARY KEY);
- INSERT INTO xx VALUES(1, 2, 3);
- CREATE TABLE xy(a, b, c PRIMARY KEY);
- ATTACH 'rbu.db' AS rbu;
- DROP TABLE IF EXISTS data_xx;
- CREATE TABLE rbu.data_xx(a, b, c, rbu_control);
- INSERT INTO data_xx VALUES(4, 5, 6, 0);
- INSERT INTO data_xx VALUES(7, 8, 9, 0);
- CREATE TABLE rbu.data_xy(a, b, c, rbu_control);
- INSERT INTO data_xy VALUES(10, 11, 12, 0);
- DETACH rbu;
- }
- do_multiclient_test tn {
- # Initialize a target (test.db) and rbu (rbu.db) database.
- #
- forcedelete rbu.db
- sql1 $setup_sql
- # Using connection 2, open a read transaction on the target database.
- # RBU will still be able to generate "test.db-oal", but it will not be
- # able to rename it to "test.db-wal".
- #
- do_test 1.$tn.1 {
- sql2 { BEGIN; SELECT * FROM xx; }
- } {1 2 3}
- do_test 1.$tn.2 {
- sqlite3rbu rbu test.db rbu.db
- while 1 {
- set res [rbu step]
- if {$res!="SQLITE_OK"} break
- }
- set res
- } {SQLITE_BUSY}
- do_test 1.$tn.3 { sql2 { SELECT * FROM xx; } } {1 2 3}
- do_test 1.$tn.4 { sql2 { SELECT * FROM xy; } } {}
- do_test 1.$tn.5 {
- list [file exists test.db-wal] [file exists test.db-oal]
- } {0 1}
- do_test 1.$tn.6 { sql2 COMMIT } {}
- # The rbu object that hit the SQLITE_BUSY error above cannot be reused.
- # It is stuck in a permanent SQLITE_BUSY state at this point.
- #
- do_test 1.$tn.7 { rbu step } {SQLITE_BUSY}
- do_test 1.$tn.8 {
- list [catch { rbu close } msg] $msg
- } {1 SQLITE_BUSY}
- do_test 1.$tn.9.1 { sql2 { BEGIN EXCLUSIVE } } {}
- do_test 1.$tn.9.2 {
- sqlite3rbu rbu test.db rbu.db
- rbu step
- } {SQLITE_BUSY}
- do_test 1.$tn.9.3 {
- list [catch { rbu close } msg] $msg
- } {1 {SQLITE_BUSY - database is locked}}
- do_test 1.$tn.9.4 { sql2 COMMIT } {}
- sqlite3rbu rbu test.db rbu.db
- do_test 1.$tn.10.1 { sql2 { BEGIN EXCLUSIVE } } {}
- do_test 1.$tn.10.2 {
- rbu step
- } {SQLITE_BUSY}
- do_test 1.$tn.10.3 {
- list [catch { rbu close } msg] $msg
- } {1 SQLITE_BUSY}
- do_test 1.$tn.10.4 { sql2 COMMIT } {}
- # A new rbu object can finish the work though.
- #
- do_test 1.$tn.11 {
- sqlite3rbu rbu test.db rbu.db
- rbu step
- } {SQLITE_OK}
- do_test 1.$tn.12 {
- list [file exists test.db-wal] [file exists test.db-oal]
- } {1 0}
- do_test 1.$tn.13 {
- while 1 {
- set res [rbu step]
- if {$res!="SQLITE_OK"} break
- }
- set res
- } {SQLITE_DONE}
- do_test 1.$tn.14 {
- rbu close
- } {SQLITE_DONE}
- }
- do_multiclient_test tn {
- # Initialize a target (test.db) and rbu (rbu.db) database.
- #
- forcedelete rbu.db
- sql1 $setup_sql
- do_test 2.$tn.1 {
- sqlite3rbu rbu test.db rbu.db
- while {[file exists test.db-wal]==0} {
- if {[rbu step]!="SQLITE_OK"} {error "problem here...."}
- }
- rbu close
- } {SQLITE_OK}
- do_test 2.$tn.2 { sql2 { BEGIN IMMEDIATE } } {}
- do_test 2.$tn.3 {
- sqlite3rbu rbu test.db rbu.db
- rbu step
- } {SQLITE_BUSY}
- do_test 2.$tn.4 { list [catch { rbu close } msg] $msg } {1 SQLITE_BUSY}
- do_test 2.$tn.5 {
- sql2 { SELECT * FROM xx ; COMMIT }
- } {1 2 3 4 5 6 7 8 9}
- do_test 2.$tn.6 {
- sqlite3rbu rbu test.db rbu.db
- rbu step
- rbu close
- } {SQLITE_OK}
- do_test 2.$tn.7 { sql2 { BEGIN EXCLUSIVE } } {}
- do_test 2.$tn.8 {
- sqlite3rbu rbu test.db rbu.db
- rbu step
- } {SQLITE_BUSY}
- do_test 2.$tn.9 { list [catch { rbu close } msg] $msg } {1 SQLITE_BUSY}
- do_test 2.$tn.10 {
- sql2 { SELECT * FROM xx ; COMMIT }
- } {1 2 3 4 5 6 7 8 9}
- do_test 2.$tn.11 {
- sqlite3rbu rbu test.db rbu.db
- while {[rbu step]=="SQLITE_OK"} {}
- rbu close
- } {SQLITE_DONE}
- }
- #-------------------------------------------------------------------------
- # Test that "PRAGMA data_version" works when an RBU client writes the
- # database.
- #
- do_multiclient_test tn {
- # Initialize a target (test.db) and rbu (rbu.db) database.
- #
- forcedelete rbu.db
- sql1 $setup_sql
- # Check the initial database contains table "xx" with a single row.
- # Also save the current values of "PRAGMA data-version" for [db1]
- # and [db2].
- #
- do_test 2.$tn.1 {
- list [sql1 { SELECT count(*) FROM xx }] [sql2 { SELECT count(*) FROM xx }]
- } {1 1}
- set V1 [sql1 {PRAGMA data_version}]
- set V2 [sql2 {PRAGMA data_version}]
- # Check the values of data-version have not magically changed.
- #
- do_test 2.$tn.2 {
- list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}]
- } [list $V1 $V2]
- # Start stepping the RBU. From the point of view of [db1] and [db2], the
- # data-version values remain unchanged until the database contents are
- # modified. At which point the values are incremented.
- #
- sqlite3rbu rbu test.db rbu.db
- set x 0
- while {[db one {SELECT count(*) FROM xx}]==1} {
- do_test 2.$tn.3.[incr x] {
- list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}]
- } [list $V1 $V2]
- rbu step
- }
- do_test 2.$tn.5.1 { expr {$V1 < [sql1 {PRAGMA data_version}]} } 1
- do_test 2.$tn.5.2 { expr {$V2 < [sql2 {PRAGMA data_version}]} } 1
- # Check the db contents is as expected.
- #
- do_test 2.$tn.4 {
- list [sql1 {SELECT count(*) FROM xx}] [sql2 {SELECT count(*) FROM xx}]
- } {3 3}
- set V1 [sql1 {PRAGMA data_version}]
- set V2 [sql2 {PRAGMA data_version}]
- # Finish applying the RBU (i.e. do the incremental checkpoint). Check that
- # this does not cause the data-version values to change.
- #
- while {[rbu step]=="SQLITE_OK"} { }
- rbu close
- do_test 2.$tn.6 {
- list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}]
- } [list $V1 $V2]
- }
- finish_test
|