1# 2018 March 14 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# This file implements regression tests for SQLite library. 12# 13 14if {![info exists testdir]} { 15 set testdir [file join [file dirname [info script]] .. .. test] 16} 17source [file join [file dirname [info script]] session_common.tcl] 18source $testdir/tester.tcl 19ifcapable !session {finish_test; return} 20 21set testprefix sessionrebase 22 23set ::lConflict [list] 24proc xConflict {args} { 25 set res [lindex $::lConflict 0] 26 set ::lConflict [lrange $::lConflict 1 end] 27 return $res 28} 29 30#------------------------------------------------------------------------- 31# The following test cases - 1.* - test that the rebase blobs output by 32# sqlite3_changeset_apply_v2 look correct in some simple cases. The blob 33# is itself a changeset, containing records determined as follows: 34# 35# * For each conflict resolved with REPLACE, the rebase blob contains 36# a DELETE record. All fields other than the PK fields are undefined. 37# 38# * For each conflict resolved with OMIT, the rebase blob contains an 39# INSERT record. For an INSERT or UPDATE operation, the indirect flag 40# is clear and all updated fields are defined. For a DELETE operation, 41# the indirect flag is set and all non-PK fields left undefined. 42# 43proc do_apply_v2_test {tn sql modsql conflict_handler res} { 44 45 execsql BEGIN 46 sqlite3session S db main 47 S attach * 48 execsql $sql 49 set changeset [S changeset] 50 S delete 51 execsql ROLLBACK 52 53 execsql BEGIN 54 execsql $modsql 55 set ::lConflict $conflict_handler 56 set blob [sqlite3changeset_apply_v2 db $changeset xConflict] 57 execsql ROLLBACK 58 59 uplevel [list do_test $tn [list changeset_to_list $blob] [list {*}$res]] 60} 61 62 63set ::lConflict [list] 64proc xConflict {args} { 65 set res [lindex $::lConflict 0] 66 set ::lConflict [lrange $::lConflict 1 end] 67 return $res 68} 69 70# Take a copy of database test.db in file test.db2. Execute $sql1 71# against test.db and $sql2 against test.db2. Capture a changeset 72# for each. Then send the test.db2 changeset to test.db and apply 73# it with the conflict handlers in $conflict_handler. Patch the 74# test.db changeset and then execute it against test.db2. Test that 75# the two databases come out the same. 76# 77proc do_rebase_test {tn sql1 sql2 conflict_handler {testsql ""} {testres ""}} { 78 79 for {set i 1} {$i <= 2} {incr i} { 80 forcedelete test.db2 test.db2-journal test.db2-wal 81 forcecopy test.db test.db2 82 sqlite3 db2 test.db2 83 84 db eval BEGIN 85 86 sqlite3session S1 db main 87 S1 attach * 88 execsql $sql1 db 89 set c1 [S1 changeset] 90 S1 delete 91 92 if {$i==1} { 93 sqlite3session S2 db2 main 94 S2 attach * 95 execsql $sql2 db2 96 set c2 [S2 changeset] 97 S2 delete 98 } else { 99 set c2 [list] 100 foreach sql [split $sql2 ";"] { 101 if {[string is space $sql]} continue 102 sqlite3session S2 db2 main 103 S2 attach * 104 execsql $sql db2 105 lappend c2 [S2 changeset] 106 S2 delete 107 } 108 } 109 110 set ::lConflict $conflict_handler 111 set rebase [list] 112 if {$i==1} { 113 lappend rebase [sqlite3changeset_apply_v2 db $c2 xConflict] 114 } else { 115 foreach c $c2 { 116 lappend rebase [sqlite3changeset_apply_v2 db $c xConflict] 117 } 118 } 119 #if {$tn=="2.1.4"} { puts [changeset_to_list $rebase] ; breakpoint } 120 #puts [changeset_to_list [lindex $rebase 0]] ; breakpoint 121 #puts [llength $rebase] 122 123if {$i==2 && $tn=="3.3.1"} breakpoint 124 sqlite3rebaser_create R 125 foreach r $rebase { 126puts [changeset_to_list $r] 127 R configure $r 128 } 129 set c1r [R rebase $c1] 130 R delete 131 #if {$tn=="2.1.4"} { puts [changeset_to_list $c1r] } 132 133 sqlite3changeset_apply_v2 db2 $c1r xConflictAbort 134 135 uplevel [list do_test $tn.$i.1 [list compare_db db db2] {}] 136 db2 close 137 138 if {$testsql!=""} { 139 uplevel [list do_execsql_test $tn.$i.2 $testsql $testres] 140 } 141 142 db eval ROLLBACK 143 } 144} 145 146do_execsql_test 1.0 { 147 CREATE TABLE t1(a INTEGER PRIMARY KEY, b); 148 INSERT INTO t1 VALUES(1, 'value A'); 149} 150 151do_apply_v2_test 1.1.1 { 152 UPDATE t1 SET b = 'value B' WHERE a=1; 153} { 154 UPDATE t1 SET b = 'value C' WHERE a=1; 155} { 156 OMIT 157} { 158 {INSERT t1 0 X. {} {i 1 t {value B}}} 159} 160 161do_apply_v2_test 1.1.2 { 162 UPDATE t1 SET b = 'value B' WHERE a=1; 163} { 164 UPDATE t1 SET b = 'value C' WHERE a=1; 165} { 166 REPLACE 167} { 168 {INSERT t1 1 X. {} {i 1 t {value B}}} 169} 170 171do_apply_v2_test 1.2.1 { 172 INSERT INTO t1 VALUES(2, 'first'); 173} { 174 INSERT INTO t1 VALUES(2, 'second'); 175} { 176 OMIT 177} { 178 {INSERT t1 0 X. {} {i 2 t first}} 179} 180do_apply_v2_test 1.2.2 { 181 INSERT INTO t1 VALUES(2, 'first'); 182} { 183 INSERT INTO t1 VALUES(2, 'second'); 184} { 185 REPLACE 186} { 187 {INSERT t1 1 X. {} {i 2 t first}} 188} 189 190do_apply_v2_test 1.3.1 { 191 DELETE FROM t1 WHERE a=1; 192} { 193 UPDATE t1 SET b='value D' WHERE a=1; 194} { 195 OMIT 196} { 197 {DELETE t1 0 X. {i 1 t {value A}} {}} 198} 199do_apply_v2_test 1.3.2 { 200 DELETE FROM t1 WHERE a=1; 201} { 202 UPDATE t1 SET b='value D' WHERE a=1; 203} { 204 REPLACE 205} { 206 {DELETE t1 1 X. {i 1 t {value A}} {}} 207} 208 209#------------------------------------------------------------------------- 210# Test cases 2.* - simple tests of rebasing actual changesets. 211# 212# 2.1.1 - 1u2u1r 213# 2.1.2 - 1u2u2r 214# 2.1.3 - 1d2d 215# 2.1.4 - 1d2u1r 216# 2.1.5 - 1d2u2r !! 217# 2.1.6 - 1u2d1r 218# 2.1.7 - 1u2d2r 219# 220# 2.1.8 - 1i2i2r 221# 2.1.9 - 1i2i1r 222# 223 224proc xConflictAbort {args} { 225 return "ABORT" 226} 227 228reset_db 229do_execsql_test 2.1.0 { 230 CREATE TABLE t1 (a INTEGER PRIMARY KEY, b TEXT); 231 INSERT INTO t1 VALUES(1, 'one'); 232 INSERT INTO t1 VALUES(2, 'two'); 233 INSERT INTO t1 VALUES(3, 'three'); 234} 235do_rebase_test 2.1.1 { 236 UPDATE t1 SET b = 'two.1' WHERE a=2 237} { 238 UPDATE t1 SET b = 'two.2' WHERE a=2; 239} { 240 OMIT 241} { SELECT * FROM t1 } {1 one 2 two.1 3 three} 242 243do_rebase_test 2.1.2 { 244 UPDATE t1 SET b = 'two.1' WHERE a=2 245} { 246 UPDATE t1 SET b = 'two.2' WHERE a=2; 247} { 248 REPLACE 249} { SELECT * FROM t1 } {1 one 2 two.2 3 three} 250 251do_rebase_test 2.1.3 { 252 DELETE FROM t1 WHERE a=3 253} { 254 DELETE FROM t1 WHERE a=3; 255} { 256 OMIT 257} { SELECT * FROM t1 } {1 one 2 two} 258 259do_rebase_test 2.1.4 { 260 DELETE FROM t1 WHERE a=1 261} { 262 UPDATE t1 SET b='one.2' WHERE a=1 263} { 264 OMIT 265} { SELECT * FROM t1 } {2 two 3 three} 266 267#do_rebase_test 2.1.5 { 268# DELETE FROM t1 WHERE a=1; 269#} { 270# UPDATE t1 SET b='one.2' WHERE a=1 271#} { 272# REPLACE 273#} { SELECT * FROM t1 } {2 two 3 three} 274 275do_rebase_test 2.1.6 { 276 UPDATE t1 SET b='three.1' WHERE a=3 277} { 278 DELETE FROM t1 WHERE a=3; 279} { 280 OMIT 281} { SELECT * FROM t1 } {1 one 2 two 3 three.1} 282 283do_rebase_test 2.1.7 { 284 UPDATE t1 SET b='three.1' WHERE a=3 285} { 286 DELETE FROM t1 WHERE a=3; 287} { 288 REPLACE 289} { SELECT * FROM t1 } {1 one 2 two} 290 291do_rebase_test 2.1.8 { 292 INSERT INTO t1 VALUES(4, 'four.1') 293} { 294 INSERT INTO t1 VALUES(4, 'four.2'); 295} { 296 REPLACE 297} { SELECT * FROM t1 } {1 one 2 two 3 three 4 four.2} 298 299do_rebase_test 2.1.9 { 300 INSERT INTO t1 VALUES(4, 'four.1') 301} { 302 INSERT INTO t1 VALUES(4, 'four.2'); 303} { 304 OMIT 305} { SELECT * FROM t1 } {1 one 2 two 3 three 4 four.1} 306 307do_execsql_test 2.2.0 { 308 CREATE TABLE t2(x, y, z PRIMARY KEY); 309 INSERT INTO t2 VALUES('i', 'a', 'A'); 310 INSERT INTO t2 VALUES('ii', 'b', 'B'); 311 INSERT INTO t2 VALUES('iii', 'c', 'C'); 312 313 CREATE TABLE t3(a INTEGER PRIMARY KEY, b, c); 314 INSERT INTO t3 VALUES(-1, 'z', 'Z'); 315 INSERT INTO t3 VALUES(-2, 'y', 'Y'); 316} 317 318do_rebase_test 2.2.1 { 319 UPDATE t2 SET x=1 WHERE z='A' 320} { 321 UPDATE t2 SET y='one' WHERE z='A'; 322} { 323} { SELECT * FROM t2 WHERE z='A' } { 1 one A } 324 325do_rebase_test 2.2.2 { 326 UPDATE t2 SET x=1, y='one' WHERE z='B' 327} { 328 UPDATE t2 SET y='two' WHERE z='B'; 329} { 330 REPLACE 331} { SELECT * FROM t2 WHERE z='B' } { 1 two B } 332 333do_rebase_test 2.2.3 { 334 UPDATE t2 SET x=1, y='one' WHERE z='B' 335} { 336 UPDATE t2 SET y='two' WHERE z='B'; 337} { 338 OMIT 339} { SELECT * FROM t2 WHERE z='B' } { 1 one B } 340 341#------------------------------------------------------------------------- 342reset_db 343do_execsql_test 3.0 { 344 CREATE TABLE t3(a, b, c, PRIMARY KEY(b, c)); 345 CREATE TABLE abcdefghijkl(x PRIMARY KEY, y, z); 346 347 INSERT INTO t3 VALUES(1, 2, 3); 348 INSERT INTO t3 VALUES(4, 2, 5); 349 INSERT INTO t3 VALUES(7, 2, 9); 350 351 INSERT INTO abcdefghijkl VALUES('a', 'b', 'c'); 352 INSERT INTO abcdefghijkl VALUES('d', 'e', 'f'); 353 INSERT INTO abcdefghijkl VALUES('g', 'h', 'i'); 354} 355 356foreach {tn p} { 357 1 OMIT 2 REPLACE 358} { 359 do_rebase_test 3.1.$tn { 360 INSERT INTO t3 VALUES(1, 1, 1); 361 UPDATE abcdefghijkl SET y=2; 362 } { 363 INSERT INTO t3 VALUES(4, 1, 1); 364 DELETE FROM abcdefghijkl; 365 } [list $p $p $p $p $p $p $p $p] 366 367 do_rebase_test 3.2.$tn { 368 INSERT INTO abcdefghijkl SELECT * FROM t3; 369 UPDATE t3 SET b=b+1; 370 } { 371 INSERT INTO t3 VALUES(3, 3, 3); 372 INSERT INTO abcdefghijkl SELECT * FROM t3; 373 } [list $p $p $p $p $p $p $p $p] 374 375 do_rebase_test 3.3.$tn { 376 INSERT INTO abcdefghijkl VALUES(22, 23, 24); 377 } { 378 INSERT INTO abcdefghijkl VALUES(22, 25, 26); 379 UPDATE abcdefghijkl SET y=400 WHERE x=22; 380 } [list $p $p $p $p $p $p $p $p] 381} 382 383finish_test 384 385