3 # The author disclaims copyright to this source code. In place of
4 # a legal notice, here is a blessing:
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.
10 #***********************************************************************
11 # This file implements regression tests for SQLite library.
14 if {![info exists testdir]} {
15 set testdir [file join [file dirname [info script]] .. .. test]
17 source [file join [file dirname [info script]] session_common.tcl]
18 source $testdir/tester.tcl
19 ifcapable !session {finish_test; return}
21 set testprefix sessionrebase
23 set ::lConflict [list]
24 proc xConflict {args} {
25 set res [lindex $::lConflict 0]
26 set ::lConflict [lrange $::lConflict 1 end]
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:
35 # * For each conflict resolved with REPLACE, the rebase blob contains
36 # a DELETE record. All fields other than the PK fields are undefined.
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.
43 proc do_apply_v2_test {tn sql modsql conflict_handler res} {
46 sqlite3session S db main
49 set changeset [S changeset]
55 set ::lConflict $conflict_handler
56 set blob [sqlite3changeset_apply_v2 db $changeset xConflict]
59 uplevel [list do_test $tn [list changeset_to_list $blob] [list {*}$res]]
63 set ::lConflict [list]
64 proc xConflict {args} {
65 set res [lindex $::lConflict 0]
66 set ::lConflict [lrange $::lConflict 1 end]
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.
77 proc do_rebase_test {tn sql1 sql2 conflict_handler {testsql ""} {testres ""}} {
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
86 sqlite3session S1 db main
87 S1 object_config rowid 1
94 sqlite3session S2 db2 main
95 S2 object_config rowid 1
102 foreach sql [split $sql2 ";"] {
103 if {[string is space $sql]} continue
104 sqlite3session S2 db2 main
105 S2 object_config rowid 1
108 lappend c2 [S2 changeset]
113 set ::lConflict $conflict_handler
116 lappend rebase [sqlite3changeset_apply_v2 db $c2 xConflict]
119 #puts "apply_v2: [changeset_to_list $c]"
120 lappend rebase [sqlite3changeset_apply_v2 db $c xConflict]
122 #puts "llength: [llength $rebase]"
124 #if {$tn=="2.1.4"} { puts [changeset_to_list $rebase] ; breakpoint }
125 #puts [changeset_to_list [lindex $rebase 0]] ; breakpoint
126 #puts [llength $rebase]
128 sqlite3rebaser_create R
130 #puts [changeset_to_list $r]
133 set c1r [R rebase $c1]
135 #if {$tn=="2.1.4"} { puts [changeset_to_list $c1r] }
137 sqlite3changeset_apply_v2 db2 $c1r xConflictAbort
139 if {[string range $tn end end]!="*"} {
140 uplevel [list do_test $tn.$i.1 [list compare_db db db2] {}]
145 uplevel [list do_execsql_test $tn.$i.2 $testsql $testres]
152 do_execsql_test 1.0 {
153 CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
154 INSERT INTO t1 VALUES(1, 'value A');
157 do_apply_v2_test 1.1.1 {
158 UPDATE t1 SET b = 'value B' WHERE a=1;
160 UPDATE t1 SET b = 'value C' WHERE a=1;
164 {INSERT t1 0 X. {} {i 1 t {value B}}}
167 do_apply_v2_test 1.1.2 {
168 UPDATE t1 SET b = 'value B' WHERE a=1;
170 UPDATE t1 SET b = 'value C' WHERE a=1;
174 {INSERT t1 1 X. {} {i 1 t {value B}}}
177 do_apply_v2_test 1.2.1 {
178 INSERT INTO t1 VALUES(2, 'first');
180 INSERT INTO t1 VALUES(2, 'second');
184 {INSERT t1 0 X. {} {i 2 t first}}
186 do_apply_v2_test 1.2.2 {
187 INSERT INTO t1 VALUES(2, 'first');
189 INSERT INTO t1 VALUES(2, 'second');
193 {INSERT t1 1 X. {} {i 2 t first}}
196 do_apply_v2_test 1.3.1 {
197 DELETE FROM t1 WHERE a=1;
199 UPDATE t1 SET b='value D' WHERE a=1;
203 {DELETE t1 0 X. {i 1 t {value A}} {}}
205 do_apply_v2_test 1.3.2 {
206 DELETE FROM t1 WHERE a=1;
208 UPDATE t1 SET b='value D' WHERE a=1;
212 {DELETE t1 1 X. {i 1 t {value A}} {}}
215 #-------------------------------------------------------------------------
216 # Test cases 2.* - simple tests of rebasing actual changesets.
230 proc xConflictAbort {args} {
235 do_execsql_test 2.1.0 {
236 CREATE TABLE t1 (a INTEGER PRIMARY KEY, b TEXT);
237 INSERT INTO t1 VALUES(1, 'one');
238 INSERT INTO t1 VALUES(2, 'two');
239 INSERT INTO t1 VALUES(3, 'three');
241 do_rebase_test 2.1.1 {
242 UPDATE t1 SET b = 'two.1' WHERE a=2
244 UPDATE t1 SET b = 'two.2' WHERE a=2;
247 } { SELECT * FROM t1 } {1 one 2 two.1 3 three}
249 do_rebase_test 2.1.2 {
250 UPDATE t1 SET b = 'two.1' WHERE a=2
252 UPDATE t1 SET b = 'two.2' WHERE a=2;
255 } { SELECT * FROM t1 } {1 one 2 two.2 3 three}
257 do_rebase_test 2.1.3 {
258 DELETE FROM t1 WHERE a=3
260 DELETE FROM t1 WHERE a=3;
263 } { SELECT * FROM t1 } {1 one 2 two}
265 do_rebase_test 2.1.4 {
266 DELETE FROM t1 WHERE a=1
268 UPDATE t1 SET b='one.2' WHERE a=1
271 } { SELECT * FROM t1 } {2 two 3 three}
273 #do_rebase_test 2.1.5 {
274 # DELETE FROM t1 WHERE a=1;
276 # UPDATE t1 SET b='one.2' WHERE a=1
279 #} { SELECT * FROM t1 } {2 two 3 three}
281 do_rebase_test 2.1.6 {
282 UPDATE t1 SET b='three.1' WHERE a=3
284 DELETE FROM t1 WHERE a=3;
287 } { SELECT * FROM t1 } {1 one 2 two 3 three.1}
289 do_rebase_test 2.1.7 {
290 UPDATE t1 SET b='three.1' WHERE a=3
292 DELETE FROM t1 WHERE a=3;
295 } { SELECT * FROM t1 } {1 one 2 two}
297 do_rebase_test 2.1.8 {
298 INSERT INTO t1 VALUES(4, 'four.1')
300 INSERT INTO t1 VALUES(4, 'four.2');
303 } { SELECT * FROM t1 } {1 one 2 two 3 three 4 four.2}
305 do_rebase_test 2.1.9 {
306 INSERT INTO t1 VALUES(4, 'four.1')
308 INSERT INTO t1 VALUES(4, 'four.2');
311 } { SELECT * FROM t1 } {1 one 2 two 3 three 4 four.1}
313 do_execsql_test 2.2.0 {
314 CREATE TABLE t2(x, y, z PRIMARY KEY);
315 INSERT INTO t2 VALUES('i', 'a', 'A');
316 INSERT INTO t2 VALUES('ii', 'b', 'B');
317 INSERT INTO t2 VALUES('iii', 'c', 'C');
319 CREATE TABLE t3(a INTEGER PRIMARY KEY, b, c);
320 INSERT INTO t3 VALUES(-1, 'z', 'Z');
321 INSERT INTO t3 VALUES(-2, 'y', 'Y');
324 do_rebase_test 2.2.1 {
325 UPDATE t2 SET x=1 WHERE z='A'
327 UPDATE t2 SET y='one' WHERE z='A';
329 } { SELECT * FROM t2 WHERE z='A' } { 1 one A }
331 do_rebase_test 2.2.2 {
332 UPDATE t2 SET x=1, y='one' WHERE z='B'
334 UPDATE t2 SET y='two' WHERE z='B';
337 } { SELECT * FROM t2 WHERE z='B' } { 1 two B }
339 do_rebase_test 2.2.3 {
340 UPDATE t2 SET x=1, y='one' WHERE z='B'
342 UPDATE t2 SET y='two' WHERE z='B';
345 } { SELECT * FROM t2 WHERE z='B' } { 1 one B }
349 do_execsql_test 2.3.0 {
350 CREATE TABLE t1 (b TEXT);
351 INSERT INTO t1(rowid, b) VALUES(1, 'one');
352 INSERT INTO t1(rowid, b) VALUES(2, 'two');
353 INSERT INTO t1(rowid, b) VALUES(3, 'three');
355 do_rebase_test 2.3.1 {
356 UPDATE t1 SET b = 'two.1' WHERE rowid=2
358 UPDATE t1 SET b = 'two.2' WHERE rowid=2;
361 } { SELECT rowid, * FROM t1 } {1 one 2 two.1 3 three}
363 do_rebase_test 2.3.2 {
364 UPDATE t1 SET b = 'two.1' WHERE rowid=2
366 UPDATE t1 SET b = 'two.2' WHERE rowid=2;
369 } { SELECT rowid, * FROM t1 } {1 one 2 two.2 3 three}
371 do_rebase_test 2.3.3 {
372 DELETE FROM t1 WHERE rowid=3
374 DELETE FROM t1 WHERE rowid=3;
377 } { SELECT rowid, * FROM t1 } {1 one 2 two}
379 do_rebase_test 2.3.4 {
380 DELETE FROM t1 WHERE rowid=1
382 UPDATE t1 SET b='one.2' WHERE rowid=1
385 } { SELECT rowid, * FROM t1 } {2 two 3 three}
387 do_rebase_test 2.3.6 {
388 UPDATE t1 SET b='three.1' WHERE rowid=3
390 DELETE FROM t1 WHERE rowid=3;
393 } { SELECT rowid, * FROM t1 } {1 one 2 two 3 three.1}
395 do_rebase_test 2.3.7 {
396 UPDATE t1 SET b='three.1' WHERE rowid=3
398 DELETE FROM t1 WHERE rowid=3;
401 } { SELECT rowid, * FROM t1 } {1 one 2 two}
403 do_rebase_test 2.3.8 {
404 INSERT INTO t1(rowid, b) VALUES(4, 'four.1')
406 INSERT INTO t1(rowid, b) VALUES(4, 'four.2');
409 } { SELECT rowid, * FROM t1 } {1 one 2 two 3 three 4 four.2}
411 do_rebase_test 2.3.9 {
412 INSERT INTO t1(rowid, b) VALUES(4, 'four.1')
414 INSERT INTO t1(rowid, b) VALUES(4, 'four.2');
417 } { SELECT rowid, * FROM t1 } {1 one 2 two 3 three 4 four.1}
420 #-------------------------------------------------------------------------
422 do_execsql_test 3.0 {
423 CREATE TABLE t3(a, b, c, PRIMARY KEY(b, c));
424 CREATE TABLE abcdefghijkl(x PRIMARY KEY, y, z);
426 INSERT INTO t3 VALUES(1, 2, 3);
427 INSERT INTO t3 VALUES(4, 2, 5);
428 INSERT INTO t3 VALUES(7, 2, 9);
430 INSERT INTO abcdefghijkl VALUES('a', 'b', 'c');
431 INSERT INTO abcdefghijkl VALUES('d', 'e', 'f');
432 INSERT INTO abcdefghijkl VALUES('g', 'h', 'i');
436 # do_rebase_test 3.6.tn {
437 # UPDATE abcdefghijkl SET z='X', y='X' WHERE x='d';
439 # UPDATE abcdefghijkl SET y=1 WHERE x='d';
440 # UPDATE abcdefghijkl SET z=1 WHERE x='d';
441 # } [list REPLACE REPLACE REPLACE]
446 do_rebase_test 3.1.$tn {
447 INSERT INTO t3 VALUES(1, 1, 1);
448 UPDATE abcdefghijkl SET y=2;
450 INSERT INTO t3 VALUES(4, 1, 1);
451 DELETE FROM abcdefghijkl;
452 } [list $p $p $p $p $p $p $p $p]
454 do_rebase_test 3.2.$tn {
455 INSERT INTO abcdefghijkl SELECT * FROM t3;
458 INSERT INTO t3 VALUES(3, 3, 3);
459 INSERT INTO abcdefghijkl SELECT * FROM t3;
460 } [list $p $p $p $p $p $p $p $p]
462 do_rebase_test 3.3.$tn {
463 INSERT INTO abcdefghijkl VALUES(22, 23, 24);
465 INSERT INTO abcdefghijkl VALUES(22, 25, 26);
466 UPDATE abcdefghijkl SET y=400 WHERE x=22;
467 } [list $p $p $p $p $p $p $p $p]
469 do_rebase_test 3.4.$tn {
470 INSERT INTO abcdefghijkl VALUES(22, 23, 24);
472 INSERT INTO abcdefghijkl VALUES(22, 25, 26);
473 UPDATE abcdefghijkl SET y=400 WHERE x=22;
476 do_rebase_test 3.5.$tn* {
477 UPDATE abcdefghijkl SET y='X' WHERE x='d';
479 DELETE FROM abcdefghijkl WHERE x='d';
480 INSERT INTO abcdefghijkl VALUES('d', NULL, NULL);
482 do_rebase_test 3.5.$tn {
483 UPDATE abcdefghijkl SET y='X' WHERE x='d';
485 DELETE FROM abcdefghijkl WHERE x='d';
486 INSERT INTO abcdefghijkl VALUES('d', NULL, NULL);
487 } [list REPLACE $p $p]
489 do_rebase_test 3.6.$tn {
490 UPDATE abcdefghijkl SET z='X', y='X' WHERE x='d';
492 UPDATE abcdefghijkl SET y=1 WHERE x='d';
493 UPDATE abcdefghijkl SET z=1 WHERE x='d';
494 } [list REPLACE $p $p]
497 #-------------------------------------------------------------------------
498 # Check that apply_v2() does not create a rebase buffer for a patchset.
499 # And that it is not possible to rebase a patchset.
501 do_execsql_test 4.0 {
502 CREATE TABLE t5(o PRIMARY KEY, p, q);
503 INSERT INTO t5 VALUES(1, 2, 3);
504 INSERT INTO t5 VALUES(4, 5, 6);
506 foreach {tn cmd rebasable} {
510 proc xConflict {args} { return "OMIT" }
514 DELETE FROM t5 WHERE o=4;
517 sqlite3session S db main
520 INSERT INTO t5 VALUES(4, 'five', 'six');
527 set ::rebase [sqlite3changeset_apply_v2 db $P xConflict]
528 expr [llength $::rebase]>0
532 foreach {tn cmd rebasable} {
537 sqlite3session S db main
540 INSERT INTO t5 VALUES(5+$tn, 'five', 'six');
545 sqlite3rebaser_create R
546 R configure $::rebase
547 expr [catch {R rebase $P}]==0