OLD | NEW |
(Empty) | |
| 1 # 2015 February 16 |
| 2 # |
| 3 # The author disclaims copyright to this source code. In place of |
| 4 # a legal notice, here is a blessing: |
| 5 # |
| 6 # May you do good and not evil. |
| 7 # May you find forgiveness for yourself and forgive others. |
| 8 # May you share freely, never taking more than you give. |
| 9 # |
| 10 #*********************************************************************** |
| 11 # |
| 12 |
| 13 if {![info exists testdir]} { |
| 14 set testdir [file join [file dirname [info script]] .. .. test] |
| 15 } |
| 16 source $testdir/tester.tcl |
| 17 source $testdir/lock_common.tcl |
| 18 set ::testprefix rbu12 |
| 19 |
| 20 set setup_sql { |
| 21 DROP TABLE IF EXISTS xx; |
| 22 DROP TABLE IF EXISTS xy; |
| 23 CREATE TABLE xx(a, b, c PRIMARY KEY); |
| 24 INSERT INTO xx VALUES(1, 2, 3); |
| 25 CREATE TABLE xy(a, b, c PRIMARY KEY); |
| 26 |
| 27 ATTACH 'rbu.db' AS rbu; |
| 28 DROP TABLE IF EXISTS data_xx; |
| 29 CREATE TABLE rbu.data_xx(a, b, c, rbu_control); |
| 30 INSERT INTO data_xx VALUES(4, 5, 6, 0); |
| 31 INSERT INTO data_xx VALUES(7, 8, 9, 0); |
| 32 CREATE TABLE rbu.data_xy(a, b, c, rbu_control); |
| 33 INSERT INTO data_xy VALUES(10, 11, 12, 0); |
| 34 DETACH rbu; |
| 35 } |
| 36 |
| 37 do_multiclient_test tn { |
| 38 |
| 39 # Initialize a target (test.db) and rbu (rbu.db) database. |
| 40 # |
| 41 forcedelete rbu.db |
| 42 sql1 $setup_sql |
| 43 |
| 44 # Using connection 2, open a read transaction on the target database. |
| 45 # RBU will still be able to generate "test.db-oal", but it will not be |
| 46 # able to rename it to "test.db-wal". |
| 47 # |
| 48 do_test 1.$tn.1 { |
| 49 sql2 { BEGIN; SELECT * FROM xx; } |
| 50 } {1 2 3} |
| 51 do_test 1.$tn.2 { |
| 52 sqlite3rbu rbu test.db rbu.db |
| 53 while 1 { |
| 54 set res [rbu step] |
| 55 if {$res!="SQLITE_OK"} break |
| 56 } |
| 57 set res |
| 58 } {SQLITE_BUSY} |
| 59 |
| 60 do_test 1.$tn.3 { sql2 { SELECT * FROM xx; } } {1 2 3} |
| 61 do_test 1.$tn.4 { sql2 { SELECT * FROM xy; } } {} |
| 62 do_test 1.$tn.5 { |
| 63 list [file exists test.db-wal] [file exists test.db-oal] |
| 64 } {0 1} |
| 65 do_test 1.$tn.6 { sql2 COMMIT } {} |
| 66 |
| 67 # The rbu object that hit the SQLITE_BUSY error above cannot be reused. |
| 68 # It is stuck in a permanent SQLITE_BUSY state at this point. |
| 69 # |
| 70 do_test 1.$tn.7 { rbu step } {SQLITE_BUSY} |
| 71 do_test 1.$tn.8 { |
| 72 list [catch { rbu close } msg] $msg |
| 73 } {1 SQLITE_BUSY} |
| 74 |
| 75 do_test 1.$tn.9.1 { sql2 { BEGIN EXCLUSIVE } } {} |
| 76 do_test 1.$tn.9.2 { |
| 77 sqlite3rbu rbu test.db rbu.db |
| 78 rbu step |
| 79 } {SQLITE_BUSY} |
| 80 do_test 1.$tn.9.3 { |
| 81 list [catch { rbu close } msg] $msg |
| 82 } {1 {SQLITE_BUSY - database is locked}} |
| 83 do_test 1.$tn.9.4 { sql2 COMMIT } {} |
| 84 |
| 85 sqlite3rbu rbu test.db rbu.db |
| 86 do_test 1.$tn.10.1 { sql2 { BEGIN EXCLUSIVE } } {} |
| 87 do_test 1.$tn.10.2 { |
| 88 rbu step |
| 89 } {SQLITE_BUSY} |
| 90 do_test 1.$tn.10.3 { |
| 91 list [catch { rbu close } msg] $msg |
| 92 } {1 SQLITE_BUSY} |
| 93 do_test 1.$tn.10.4 { sql2 COMMIT } {} |
| 94 |
| 95 # A new rbu object can finish the work though. |
| 96 # |
| 97 do_test 1.$tn.11 { |
| 98 sqlite3rbu rbu test.db rbu.db |
| 99 rbu step |
| 100 } {SQLITE_OK} |
| 101 do_test 1.$tn.12 { |
| 102 list [file exists test.db-wal] [file exists test.db-oal] |
| 103 } {1 0} |
| 104 do_test 1.$tn.13 { |
| 105 while 1 { |
| 106 set res [rbu step] |
| 107 if {$res!="SQLITE_OK"} break |
| 108 } |
| 109 set res |
| 110 } {SQLITE_DONE} |
| 111 |
| 112 do_test 1.$tn.14 { |
| 113 rbu close |
| 114 } {SQLITE_DONE} |
| 115 } |
| 116 |
| 117 do_multiclient_test tn { |
| 118 |
| 119 # Initialize a target (test.db) and rbu (rbu.db) database. |
| 120 # |
| 121 forcedelete rbu.db |
| 122 sql1 $setup_sql |
| 123 |
| 124 do_test 2.$tn.1 { |
| 125 sqlite3rbu rbu test.db rbu.db |
| 126 while {[file exists test.db-wal]==0} { |
| 127 if {[rbu step]!="SQLITE_OK"} {error "problem here...."} |
| 128 } |
| 129 rbu close |
| 130 } {SQLITE_OK} |
| 131 |
| 132 |
| 133 do_test 2.$tn.2 { sql2 { BEGIN IMMEDIATE } } {} |
| 134 |
| 135 do_test 2.$tn.3 { |
| 136 sqlite3rbu rbu test.db rbu.db |
| 137 rbu step |
| 138 } {SQLITE_BUSY} |
| 139 |
| 140 do_test 2.$tn.4 { list [catch { rbu close } msg] $msg } {1 SQLITE_BUSY} |
| 141 |
| 142 do_test 2.$tn.5 { |
| 143 sql2 { SELECT * FROM xx ; COMMIT } |
| 144 } {1 2 3 4 5 6 7 8 9} |
| 145 |
| 146 do_test 2.$tn.6 { |
| 147 sqlite3rbu rbu test.db rbu.db |
| 148 rbu step |
| 149 rbu close |
| 150 } {SQLITE_OK} |
| 151 |
| 152 do_test 2.$tn.7 { sql2 { BEGIN EXCLUSIVE } } {} |
| 153 |
| 154 do_test 2.$tn.8 { |
| 155 sqlite3rbu rbu test.db rbu.db |
| 156 rbu step |
| 157 } {SQLITE_BUSY} |
| 158 do_test 2.$tn.9 { list [catch { rbu close } msg] $msg } {1 SQLITE_BUSY} |
| 159 do_test 2.$tn.10 { |
| 160 sql2 { SELECT * FROM xx ; COMMIT } |
| 161 } {1 2 3 4 5 6 7 8 9} |
| 162 |
| 163 do_test 2.$tn.11 { |
| 164 sqlite3rbu rbu test.db rbu.db |
| 165 while {[rbu step]=="SQLITE_OK"} {} |
| 166 rbu close |
| 167 } {SQLITE_DONE} |
| 168 |
| 169 } |
| 170 |
| 171 #------------------------------------------------------------------------- |
| 172 # Test that "PRAGMA data_version" works when an RBU client writes the |
| 173 # database. |
| 174 # |
| 175 do_multiclient_test tn { |
| 176 |
| 177 # Initialize a target (test.db) and rbu (rbu.db) database. |
| 178 # |
| 179 forcedelete rbu.db |
| 180 sql1 $setup_sql |
| 181 |
| 182 # Check the initial database contains table "xx" with a single row. |
| 183 # Also save the current values of "PRAGMA data-version" for [db1] |
| 184 # and [db2]. |
| 185 # |
| 186 do_test 2.$tn.1 { |
| 187 list [sql1 { SELECT count(*) FROM xx }] [sql2 { SELECT count(*) FROM xx }] |
| 188 } {1 1} |
| 189 set V1 [sql1 {PRAGMA data_version}] |
| 190 set V2 [sql2 {PRAGMA data_version}] |
| 191 |
| 192 # Check the values of data-version have not magically changed. |
| 193 # |
| 194 do_test 2.$tn.2 { |
| 195 list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}] |
| 196 } [list $V1 $V2] |
| 197 |
| 198 # Start stepping the RBU. From the point of view of [db1] and [db2], the |
| 199 # data-version values remain unchanged until the database contents are |
| 200 # modified. At which point the values are incremented. |
| 201 # |
| 202 sqlite3rbu rbu test.db rbu.db |
| 203 set x 0 |
| 204 while {[db one {SELECT count(*) FROM xx}]==1} { |
| 205 do_test 2.$tn.3.[incr x] { |
| 206 list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}] |
| 207 } [list $V1 $V2] |
| 208 rbu step |
| 209 } |
| 210 do_test 2.$tn.5.1 { expr {$V1 < [sql1 {PRAGMA data_version}]} } 1 |
| 211 do_test 2.$tn.5.2 { expr {$V2 < [sql2 {PRAGMA data_version}]} } 1 |
| 212 |
| 213 # Check the db contents is as expected. |
| 214 # |
| 215 do_test 2.$tn.4 { |
| 216 list [sql1 {SELECT count(*) FROM xx}] [sql2 {SELECT count(*) FROM xx}] |
| 217 } {3 3} |
| 218 |
| 219 set V1 [sql1 {PRAGMA data_version}] |
| 220 set V2 [sql2 {PRAGMA data_version}] |
| 221 |
| 222 # Finish applying the RBU (i.e. do the incremental checkpoint). Check that |
| 223 # this does not cause the data-version values to change. |
| 224 # |
| 225 while {[rbu step]=="SQLITE_OK"} { } |
| 226 rbu close |
| 227 |
| 228 do_test 2.$tn.6 { |
| 229 list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}] |
| 230 } [list $V1 $V2] |
| 231 |
| 232 } |
| 233 |
| 234 finish_test |
| 235 |
OLD | NEW |