OLD | NEW |
(Empty) | |
| 1 # 2016 March 18 |
| 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 source [file join [file dirname [info script]] rbu_common.tcl] |
| 14 set ::testprefix rbuprogress |
| 15 |
| 16 |
| 17 proc create_db_file {filename sql} { |
| 18 forcedelete $filename |
| 19 sqlite3 tmpdb $filename |
| 20 tmpdb eval $sql |
| 21 tmpdb close |
| 22 } |
| 23 |
| 24 # Create a simple RBU database. That expects to write to a table: |
| 25 # |
| 26 # CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); |
| 27 # |
| 28 proc create_rbu1 {filename} { |
| 29 create_db_file $filename { |
| 30 CREATE TABLE data_t1(a, b, c, rbu_control); |
| 31 INSERT INTO data_t1 VALUES(1, 2, 3, 0); |
| 32 INSERT INTO data_t1 VALUES(2, 'two', 'three', 0); |
| 33 INSERT INTO data_t1 VALUES(3, NULL, 8.2, 0); |
| 34 |
| 35 CREATE TABLE rbu_count(tbl, cnt); |
| 36 INSERT INTO rbu_count VALUES('data_t1', 3); |
| 37 } |
| 38 return $filename |
| 39 } |
| 40 |
| 41 |
| 42 do_execsql_test 1.0 { |
| 43 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); |
| 44 } |
| 45 |
| 46 do_test 1.1 { |
| 47 create_rbu1 rbu.db |
| 48 sqlite3rbu rbu test.db rbu.db |
| 49 rbu bp_progress |
| 50 } {0 0} |
| 51 do_test 1.2 { rbu step ; rbu bp_progress } {3333 0} |
| 52 do_test 1.3 { rbu step ; rbu bp_progress } {6666 0} |
| 53 do_test 1.4 { rbu step ; rbu bp_progress } {10000 0} |
| 54 do_test 1.5 { rbu step ; rbu bp_progress } {10000 0} |
| 55 do_test 1.6 { rbu step ; rbu bp_progress } {10000 0} |
| 56 do_test 1.7 { rbu step ; rbu bp_progress } {10000 5000} |
| 57 do_test 1.8 { rbu step ; rbu bp_progress } {10000 10000} |
| 58 do_test 1.9 { rbu step ; rbu bp_progress } {10000 10000} |
| 59 |
| 60 do_test 1.10 { |
| 61 rbu close |
| 62 } {SQLITE_DONE} |
| 63 |
| 64 #------------------------------------------------------------------------- |
| 65 # |
| 66 proc do_sp_test {tn bReopen target rbu reslist} { |
| 67 uplevel [list do_test $tn [subst -nocommands { |
| 68 if {$bReopen==0} { sqlite3rbu rbu $target $rbu } |
| 69 set res [list] |
| 70 while 1 { |
| 71 if {$bReopen} { sqlite3rbu rbu $target $rbu } |
| 72 set rc [rbu step] |
| 73 if {[set rc] != "SQLITE_OK"} { rbu close ; error "error 1" } |
| 74 lappend res [lindex [rbu bp_progress] 0] |
| 75 if {[lindex [set res] end]==10000} break |
| 76 if {$bReopen} { rbu close } |
| 77 } |
| 78 if {[set res] != [list $reslist]} { |
| 79 rbu close |
| 80 error "1. reslist incorrect (expect=$reslist got=[set res])" |
| 81 } |
| 82 |
| 83 # One step to clean up the temporary tables used to update the only |
| 84 # target table in the rbu database. And one more to move the *-oal |
| 85 # file to *-wal. After each of these steps, the progress remains |
| 86 # at "10000 0". |
| 87 # |
| 88 if {[lindex [list $reslist] 0]!=-1} { |
| 89 rbu step |
| 90 set res [rbu bp_progress] |
| 91 if {[set res] != [list 10000 0]} { |
| 92 rbu close |
| 93 error "2. reslist incorrect (expect=10000 0 got=[set res])" |
| 94 } |
| 95 } |
| 96 |
| 97 rbu step |
| 98 set res [rbu bp_progress] |
| 99 if {[set res] != [list 10000 0]} { |
| 100 rbu close |
| 101 error "3. reslist incorrect (expect=10000 0 got=[set res])" |
| 102 } |
| 103 |
| 104 # Do the checkpoint. |
| 105 while {[rbu step]=="SQLITE_OK"} { |
| 106 foreach {a b} [rbu bp_progress] {} |
| 107 if {[set a]!=10000 || [set b]<=0 || [set b]>10000} { |
| 108 rbu close |
| 109 error "4. reslist incorrect (expect=10000 1..10000 got=[set a] [set b])" |
| 110 } |
| 111 } |
| 112 |
| 113 set res [rbu bp_progress] |
| 114 if {[set res] != [list 10000 10000]} { |
| 115 rbu close |
| 116 error "5. reslist is incorrect (expect=10000 10000 got=[set res])" |
| 117 } |
| 118 |
| 119 rbu close |
| 120 }] {SQLITE_DONE}] |
| 121 } |
| 122 |
| 123 foreach {bReopen} { 0 1 } { |
| 124 reset_db |
| 125 do_test 2.$bReopen.1.0 { |
| 126 execsql { |
| 127 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); |
| 128 } |
| 129 create_db_file rbu.db { |
| 130 CREATE TABLE data_t1(a, b, c, rbu_control); |
| 131 INSERT INTO data_t1 VALUES(4, 4, 4, 0); |
| 132 INSERT INTO data_t1 VALUES(5, 5, 5, 0); |
| 133 |
| 134 CREATE TABLE rbu_count(tbl, cnt); |
| 135 INSERT INTO rbu_count VALUES('data_t1', 2); |
| 136 } |
| 137 } {} |
| 138 do_sp_test 2.$bReopen.1.1 $bReopen test.db rbu.db {5000 10000} |
| 139 |
| 140 reset_db |
| 141 do_test 2.$bReopen.2.0 { |
| 142 execsql { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c) } |
| 143 create_rbu1 rbu.db |
| 144 } {rbu.db} |
| 145 do_sp_test 2.$bReopen.2.1 $bReopen test.db rbu.db {3333 6666 10000} |
| 146 |
| 147 reset_db |
| 148 do_test 2.$bReopen.3.0 { |
| 149 execsql { |
| 150 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); |
| 151 CREATE INDEX i1 ON t1(b); |
| 152 INSERT INTO t1 VALUES(1, 1, 1); |
| 153 INSERT INTO t1 VALUES(2, 2, 2); |
| 154 INSERT INTO t1 VALUES(3, 3, 3); |
| 155 } |
| 156 create_db_file rbu.db { |
| 157 CREATE TABLE data_t1(a, b, c, rbu_control); |
| 158 INSERT INTO data_t1 VALUES(4, 4, 4, 0); |
| 159 INSERT INTO data_t1 VALUES(2, NULL, NULL, 1); |
| 160 INSERT INTO data_t1 VALUES(5, NULL, NULL, 1); |
| 161 |
| 162 CREATE TABLE rbu_count(tbl, cnt); |
| 163 INSERT INTO rbu_count VALUES('data_t1', 3); |
| 164 } |
| 165 } {} |
| 166 do_sp_test 2.$bReopen.3.1 $bReopen test.db rbu.db {1666 3333 6000 8000 10000} |
| 167 |
| 168 reset_db |
| 169 do_test 2.$bReopen.4.0 { |
| 170 execsql { |
| 171 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); |
| 172 CREATE INDEX i1 ON t1(b); |
| 173 INSERT INTO t1 VALUES(1, 1, 1); |
| 174 INSERT INTO t1 VALUES(2, 2, 2); |
| 175 INSERT INTO t1 VALUES(3, 3, 3); |
| 176 } |
| 177 create_db_file rbu.db { |
| 178 CREATE TABLE data_t1(a, b, c, rbu_control); |
| 179 INSERT INTO data_t1 VALUES(2, 4, 4, '.xx'); |
| 180 |
| 181 CREATE TABLE rbu_count(tbl, cnt); |
| 182 INSERT INTO rbu_count VALUES('data_t1', 1); |
| 183 } |
| 184 } {} |
| 185 do_sp_test 2.$bReopen.4.1 $bReopen test.db rbu.db {3333 6666 10000} |
| 186 |
| 187 reset_db |
| 188 do_test 2.$bReopen.5.0 { |
| 189 execsql { |
| 190 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); |
| 191 CREATE INDEX i1 ON t1(b); |
| 192 INSERT INTO t1 VALUES(1, 1, 1); |
| 193 INSERT INTO t1 VALUES(2, 2, 2); |
| 194 INSERT INTO t1 VALUES(3, 3, 3); |
| 195 } |
| 196 create_db_file rbu.db { |
| 197 CREATE TABLE data_t1(a, b, c, rbu_control); |
| 198 INSERT INTO data_t1 VALUES(4, NULL, 4, '.xx'); |
| 199 |
| 200 CREATE TABLE rbu_count(tbl, cnt); |
| 201 INSERT INTO rbu_count VALUES('data_t1', 1); |
| 202 } |
| 203 } {} |
| 204 do_sp_test 2.$bReopen.5.1 $bReopen test.db rbu.db {10000} |
| 205 |
| 206 reset_db |
| 207 do_test 2.$bReopen.6.0 { |
| 208 execsql { |
| 209 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); |
| 210 CREATE INDEX i1 ON t1(b); |
| 211 INSERT INTO t1 VALUES(1, 1, 1); |
| 212 INSERT INTO t1 VALUES(2, 2, 2); |
| 213 INSERT INTO t1 VALUES(3, 3, 3); |
| 214 } |
| 215 create_db_file rbu.db { |
| 216 CREATE TABLE data_t1(a, b, c, rbu_control); |
| 217 INSERT INTO data_t1 VALUES(4, 4, 4, 0); |
| 218 INSERT INTO data_t1 VALUES(2, NULL, NULL, 1); |
| 219 INSERT INTO data_t1 VALUES(5, NULL, NULL, 1); |
| 220 } |
| 221 } {} |
| 222 do_sp_test 2.$bReopen.6.1 $bReopen test.db rbu.db {-1 -1 -1 -1 -1 10000} |
| 223 } |
| 224 |
| 225 #------------------------------------------------------------------------- |
| 226 # The following tests verify that the API works when resuming an update |
| 227 # during the incremental checkpoint stage. |
| 228 # |
| 229 proc do_phase2_test {tn bReopen target rbu nStep} { |
| 230 uplevel [list do_test $tn [subst -nocommands { |
| 231 |
| 232 # Build the OAL/WAL file: |
| 233 sqlite3rbu rbu $target $rbu |
| 234 while {[lindex [rbu bp_progress] 0]<10000} { |
| 235 set rc [rbu step] |
| 236 if {"SQLITE_OK" != [set rc]} { rbu close } |
| 237 } |
| 238 |
| 239 # Clean up the temp tables and move the *-oal file to *-wal. |
| 240 rbu step |
| 241 rbu step |
| 242 |
| 243 for {set i 0} {[set i] < $nStep} {incr i} { |
| 244 if {$bReopen} { |
| 245 rbu close |
| 246 sqlite3rbu rbu $target $rbu |
| 247 } |
| 248 rbu step |
| 249 set res [rbu bp_progress] |
| 250 set expect [expr (1 + [set i]) * 10000 / $nStep] |
| 251 if {[lindex [set res] 1] != [set expect]} { |
| 252 error "Have [set res], expected 10000 [set expect]" |
| 253 } |
| 254 } |
| 255 |
| 256 set rc [rbu step] |
| 257 if {[set rc] != "SQLITE_DONE"} { |
| 258 error "Have [set rc], expected SQLITE_DONE" |
| 259 } |
| 260 |
| 261 rbu close |
| 262 }] {SQLITE_DONE}] |
| 263 } |
| 264 |
| 265 foreach bReopen {0 1} { |
| 266 do_test 3.$bReopen.1.0 { |
| 267 reset_db |
| 268 execsql { |
| 269 CREATE TABLE t1(a INTEGER PRIMARY KEY, b); |
| 270 CREATE TABLE t2(a INTEGER PRIMARY KEY, b); |
| 271 CREATE TABLE t3(a INTEGER PRIMARY KEY, b); |
| 272 CREATE TABLE t4(a INTEGER PRIMARY KEY, b); |
| 273 } |
| 274 create_db_file rbu.db { |
| 275 CREATE TABLE data_t1(a, b, rbu_control); |
| 276 CREATE TABLE data_t2(a, b, rbu_control); |
| 277 CREATE TABLE data_t3(a, b, rbu_control); |
| 278 CREATE TABLE data_t4(a, b, rbu_control); |
| 279 INSERT INTO data_t1 VALUES(1, 2, 0); |
| 280 INSERT INTO data_t2 VALUES(1, 2, 0); |
| 281 INSERT INTO data_t3 VALUES(1, 2, 0); |
| 282 INSERT INTO data_t4 VALUES(1, 2, 0); |
| 283 |
| 284 CREATE TABLE rbu_count(tbl, cnt); |
| 285 INSERT INTO rbu_count VALUES('data_t1', 1); |
| 286 INSERT INTO rbu_count VALUES('data_t2', 1); |
| 287 INSERT INTO rbu_count VALUES('data_t3', 1); |
| 288 INSERT INTO rbu_count VALUES('data_t4', 1); |
| 289 } |
| 290 } {} |
| 291 do_phase2_test 3.$bReopen.1.1 $bReopen test.db rbu.db 5 |
| 292 } |
| 293 |
| 294 |
| 295 foreach {bReopen} { 0 1 } { |
| 296 foreach {tn tbl} { |
| 297 ipk { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c) } |
| 298 wr { CREATE TABLE t1(a INT PRIMARY KEY, b, c) WITHOUT ROWID } |
| 299 pk { CREATE TABLE t1(a INT PRIMARY KEY, b, c) } |
| 300 } { |
| 301 |
| 302 foreach {tn2 rbusql r1 r3} { |
| 303 1 { |
| 304 CREATE TABLE data0_t1(a, b, c, rbu_control); |
| 305 INSERT INTO data0_t1 VALUES(15, 15, 15, 0); |
| 306 INSERT INTO data0_t1 VALUES(20, 20, 20, 0); |
| 307 CREATE TABLE rbu_count(tbl, cnt); |
| 308 INSERT INTO rbu_count VALUES('data0_t1', 2); |
| 309 } |
| 310 {2500 5000 7500 10000} |
| 311 {1666 3333 5000 6666 8333 10000} |
| 312 |
| 313 2 { |
| 314 CREATE TABLE data0_t1(a, b, c, rbu_control); |
| 315 INSERT INTO data0_t1 VALUES(10, 10, 10, 2); |
| 316 CREATE TABLE rbu_count(tbl, cnt); |
| 317 INSERT INTO rbu_count VALUES('data0_t1', 1); |
| 318 } |
| 319 {3333 6666 10000} |
| 320 {2000 4000 6000 8000 10000} |
| 321 |
| 322 3 { |
| 323 CREATE TABLE data0_t1(a, b, c, rbu_control); |
| 324 INSERT INTO data0_t1 VALUES(7, 7, 7, 2); |
| 325 INSERT INTO data0_t1 VALUES(10, 10, 10, 2); |
| 326 CREATE TABLE rbu_count(tbl, cnt); |
| 327 INSERT INTO rbu_count VALUES('data0_t1', 2); |
| 328 } |
| 329 {2500 4000 6000 8000 10000} |
| 330 {1666 2500 3750 5000 6250 7500 8750 10000} |
| 331 |
| 332 } { |
| 333 |
| 334 reset_db ; execsql $tbl |
| 335 do_test 4.$tn.$bReopen.$tn2.0 { |
| 336 execsql { |
| 337 CREATE INDEX t1c ON t1(c); |
| 338 INSERT INTO t1 VALUES(1, 1, 1); |
| 339 INSERT INTO t1 VALUES(5, 5, 5); |
| 340 INSERT INTO t1 VALUES(10, 10, 10); |
| 341 } |
| 342 create_db_file rbu.db $rbusql |
| 343 } {} |
| 344 |
| 345 set R(ipk) $r1 |
| 346 set R(wr) $r1 |
| 347 set R(pk) $r3 |
| 348 do_sp_test 4.$tn.$bReopen.$tn2.1 $bReopen test.db rbu.db $R($tn) |
| 349 } |
| 350 } |
| 351 } |
| 352 |
| 353 foreach {bReopen} { 0 1 } { |
| 354 foreach {tn tbl} { |
| 355 nopk { |
| 356 CREATE TABLE t1(a, b, c); |
| 357 CREATE INDEX t1c ON t1(c); |
| 358 } |
| 359 vtab { |
| 360 CREATE VIRTUAL TABLE t1 USING fts5(a, b, c); |
| 361 } |
| 362 } { |
| 363 |
| 364 if {$tn=="vtab"} { ifcapable !fts5 break } |
| 365 |
| 366 foreach {tn2 rbusql r1 r2} { |
| 367 1 { |
| 368 CREATE TABLE data0_t1(a, b, c, rbu_rowid, rbu_control); |
| 369 INSERT INTO data0_t1 VALUES(15, 15, 15, 4, 0); |
| 370 INSERT INTO data0_t1 VALUES(20, 20, 20, 5, 0); |
| 371 CREATE TABLE rbu_count(tbl, cnt); |
| 372 INSERT INTO rbu_count VALUES('data0_t1', 2); |
| 373 } |
| 374 {2500 5000 7500 10000} |
| 375 {5000 10000} |
| 376 |
| 377 2 { |
| 378 CREATE TABLE data0_t1(rbu_rowid, a, b, c, rbu_control); |
| 379 INSERT INTO data0_t1 VALUES(0, 7, 7, 7, 2); |
| 380 INSERT INTO data0_t1 VALUES(2, 10, 10, 10, 2); |
| 381 CREATE TABLE rbu_count(tbl, cnt); |
| 382 INSERT INTO rbu_count VALUES('data0_t1', 2); |
| 383 } |
| 384 {2500 4000 6000 8000 10000} |
| 385 {5000 10000} |
| 386 |
| 387 3 { |
| 388 CREATE TABLE data0_t1(rbu_rowid, a, b, c, rbu_control); |
| 389 INSERT INTO data0_t1 VALUES(1, NULL, NULL, NULL, 1); |
| 390 INSERT INTO data0_t1 VALUES(2, NULL, NULL, 7, '..x'); |
| 391 CREATE TABLE rbu_count(tbl, cnt); |
| 392 INSERT INTO rbu_count VALUES('data0_t1', 2); |
| 393 } |
| 394 {2500 4000 6000 8000 10000} |
| 395 {5000 10000} |
| 396 } { |
| 397 |
| 398 reset_db ; execsql $tbl |
| 399 do_test 5.$tn.$bReopen.$tn2.0 { |
| 400 execsql { |
| 401 INSERT INTO t1 VALUES(1, 1, 1); |
| 402 INSERT INTO t1 VALUES(5, 5, 5); |
| 403 INSERT INTO t1 VALUES(10, 10, 10); |
| 404 } |
| 405 create_db_file rbu.db $rbusql |
| 406 } {} |
| 407 |
| 408 set R(nopk) $r1 |
| 409 set R(vtab) $r2 |
| 410 do_sp_test 5.$tn.$bReopen.$tn2.1 $bReopen test.db rbu.db $R($tn) |
| 411 } |
| 412 } |
| 413 } |
| 414 |
| 415 |
| 416 finish_test |
| 417 |
OLD | NEW |