15d607a6eSdan# 2011 April 13 25d607a6eSdan# 35d607a6eSdan# The author disclaims copyright to this source code. In place of 45d607a6eSdan# a legal notice, here is a blessing: 55d607a6eSdan# 65d607a6eSdan# May you do good and not evil. 75d607a6eSdan# May you find forgiveness for yourself and forgive others. 85d607a6eSdan# May you share freely, never taking more than you give. 95d607a6eSdan# 105d607a6eSdan#*********************************************************************** 115d607a6eSdan# This file implements regression tests for the session module. 125d607a6eSdan# Specifically, for the sqlite3changeset_concat() command. 135d607a6eSdan# 145d607a6eSdan 155d607a6eSdanif {![info exists testdir]} { 165d607a6eSdan set testdir [file join [file dirname [info script]] .. .. test] 175d607a6eSdan} 185d607a6eSdansource [file join [file dirname [info script]] session_common.tcl] 195d607a6eSdansource $testdir/tester.tcl 205d607a6eSdanifcapable !session {finish_test; return} 215d607a6eSdan 225d607a6eSdanset testprefix session5 235d607a6eSdan 246cda207fSdan# Organization of tests: 256cda207fSdan# 266cda207fSdan# session5-1.*: Simple tests to check the concat() function produces 276cda207fSdan# correct results. 286cda207fSdan# 296cda207fSdan# session5-2.*: More complicated tests. 306cda207fSdan# 316cda207fSdan# session5-3.*: Schema mismatch errors. 326cda207fSdan# 33*6734007dSdan# session5-4.*: Test the concat cases that indicate that the database 34*6734007dSdan# was modified in between recording of the two changesets 35*6734007dSdan# being concatenated (i.e. two changesets that INSERT rows 36*6734007dSdan# with the same PK values). 37*6734007dSdan# 385d607a6eSdan 396cda207fSdanproc do_concat_test {tn args} { 405d607a6eSdan 416cda207fSdan set subtest 0 426cda207fSdan foreach sql $args { 436cda207fSdan incr subtest 446cda207fSdan sqlite3session S db main ; S attach * 456cda207fSdan execsql $sql 465d607a6eSdan 476cda207fSdan set c [S changeset] 486cda207fSdan if {[info commands s_prev] != ""} { 496cda207fSdan set c_concat [sqlite3changeset_concat $c_prev $c] 506cda207fSdan set c_two [s_prev changeset] 516cda207fSdan s_prev delete 525d607a6eSdan 536cda207fSdan set h_concat [changeset_to_list $c_concat] 546cda207fSdan set h_two [changeset_to_list $c_two] 555d607a6eSdan 566cda207fSdan do_test $tn.$subtest [list set {} $h_concat] $h_two 576cda207fSdan } 586cda207fSdan set c_prev $c 596cda207fSdan rename S s_prev 606cda207fSdan } 615d607a6eSdan 626cda207fSdan catch { s_prev delete } 635d607a6eSdan} 645d607a6eSdan 65f29123b5Sdan#------------------------------------------------------------------------- 66f29123b5Sdan# Test cases session5-1.* - simple tests. 67f29123b5Sdan# 685d607a6eSdando_execsql_test 1.0 { 695d607a6eSdan CREATE TABLE t1(a PRIMARY KEY, b); 705d607a6eSdan} 715d607a6eSdan 725d607a6eSdando_concat_test 1.1.1 { 735d607a6eSdan INSERT INTO t1 VALUES(1, 'one'); 745d607a6eSdan} { 755d607a6eSdan INSERT INTO t1 VALUES(2, 'two'); 765d607a6eSdan} 775d607a6eSdan 785d607a6eSdando_concat_test 1.1.2 { 795d607a6eSdan UPDATE t1 SET b = 'five' WHERE a = 1; 805d607a6eSdan} { 815d607a6eSdan UPDATE t1 SET b = 'six' WHERE a = 2; 825d607a6eSdan} 835d607a6eSdan 845d607a6eSdando_concat_test 1.1.3 { 855d607a6eSdan DELETE FROM t1 WHERE a = 1; 865d607a6eSdan} { 875d607a6eSdan DELETE FROM t1 WHERE a = 2; 885d607a6eSdan} 895d607a6eSdan 905d607a6eSdan 915d607a6eSdan# 1.2.1: INSERT + DELETE -> (none) 925d607a6eSdan# 1.2.2: INSERT + UPDATE -> INSERT 935d607a6eSdan# 945d607a6eSdan# 1.2.3: DELETE + INSERT (matching data) -> (none) 955d607a6eSdan# 1.2.4: DELETE + INSERT (non-matching data) -> UPDATE 965d607a6eSdan# 975d607a6eSdan# 1.2.5: UPDATE + UPDATE (matching data) -> (none) 985d607a6eSdan# 1.2.6: UPDATE + UPDATE (non-matching data) -> UPDATE 995d607a6eSdan# 1.2.7: UPDATE + DELETE -> DELETE 1005d607a6eSdan# 1015d607a6eSdando_concat_test 1.2.1 { 1025d607a6eSdan INSERT INTO t1 VALUES('x', 'y'); 1035d607a6eSdan} { 1045d607a6eSdan DELETE FROM t1 WHERE a = 'x'; 1055d607a6eSdan} 1065d607a6eSdando_concat_test 1.2.2 { 1075d607a6eSdan INSERT INTO t1 VALUES(5.0, 'five'); 1085d607a6eSdan} { 1095d607a6eSdan UPDATE t1 SET b = 'six' WHERE a = 5.0; 1105d607a6eSdan} 1115d607a6eSdan 1125d607a6eSdando_execsql_test 1.2.3.1 "INSERT INTO t1 VALUES('I', 'one')" 1135d607a6eSdando_concat_test 1.2.3.2 { 1145d607a6eSdan DELETE FROM t1 WHERE a = 'I'; 1155d607a6eSdan} { 1165d607a6eSdan INSERT INTO t1 VALUES('I', 'one'); 1175d607a6eSdan} 1185d607a6eSdando_concat_test 1.2.4 { 1195d607a6eSdan DELETE FROM t1 WHERE a = 'I'; 1205d607a6eSdan} { 1215d607a6eSdan INSERT INTO t1 VALUES('I', 'two'); 1225d607a6eSdan} 1235d607a6eSdando_concat_test 1.2.5 { 1245d607a6eSdan UPDATE t1 SET b = 'five' WHERE a = 'I'; 1255d607a6eSdan} { 1265d607a6eSdan UPDATE t1 SET b = 'two' WHERE a = 'I'; 1275d607a6eSdan} 1285d607a6eSdando_concat_test 1.2.6 { 1295d607a6eSdan UPDATE t1 SET b = 'six' WHERE a = 'I'; 1305d607a6eSdan} { 1315d607a6eSdan UPDATE t1 SET b = 'seven' WHERE a = 'I'; 1325d607a6eSdan} 1335d607a6eSdando_concat_test 1.2.7 { 1345d607a6eSdan UPDATE t1 SET b = 'eight' WHERE a = 'I'; 1355d607a6eSdan} { 1365d607a6eSdan DELETE FROM t1 WHERE a = 'I'; 1375d607a6eSdan} 1385d607a6eSdan 139f29123b5Sdan 140f29123b5Sdan#------------------------------------------------------------------------- 141f29123b5Sdan# Test cases session5-2.* - more complex tests. 142f29123b5Sdan# 1436cda207fSdandb function indirect indirect 1446cda207fSdanproc indirect {{x -1}} { 1456cda207fSdan S indirect $x 1466cda207fSdan s_prev indirect $x 1476cda207fSdan} 1486cda207fSdando_concat_test 2.1 { 1496cda207fSdan CREATE TABLE abc(a, b, c PRIMARY KEY); 1506cda207fSdan INSERT INTO abc VALUES(NULL, NULL, 1); 1516cda207fSdan INSERT INTO abc VALUES('abcdefghijkl', NULL, 2); 1526cda207fSdan} { 1536cda207fSdan DELETE FROM abc WHERE c = 1; 1546cda207fSdan UPDATE abc SET c = 1 WHERE c = 2; 1556cda207fSdan} { 1566cda207fSdan INSERT INTO abc VALUES('abcdefghijkl', NULL, 2); 1576cda207fSdan INSERT INTO abc VALUES(1.0, 2.0, 3); 1586cda207fSdan} { 1596cda207fSdan UPDATE abc SET a = a-1; 1606cda207fSdan} { 1616cda207fSdan CREATE TABLE def(d, e, f, PRIMARY KEY(e, f)); 1626cda207fSdan INSERT INTO def VALUES('x', randomblob(11000), 67); 1636cda207fSdan INSERT INTO def SELECT d, e, f+1 FROM def; 1646cda207fSdan INSERT INTO def SELECT d, e, f+2 FROM def; 1656cda207fSdan INSERT INTO def SELECT d, e, f+4 FROM def; 1666cda207fSdan} { 1676cda207fSdan DELETE FROM def WHERE rowid>4; 1686cda207fSdan} { 1696cda207fSdan INSERT INTO def SELECT d, e, f+4 FROM def; 1706cda207fSdan} { 1716cda207fSdan INSERT INTO abc VALUES(22, 44, -1); 1726cda207fSdan} { 1736cda207fSdan UPDATE abc SET c=-2 WHERE c=-1; 1746cda207fSdan UPDATE abc SET c=-3 WHERE c=-2; 1756cda207fSdan} { 1766cda207fSdan UPDATE abc SET c=-4 WHERE c=-3; 1776cda207fSdan} { 1786cda207fSdan UPDATE abc SET a=a+1 WHERE c=-3; 1796cda207fSdan UPDATE abc SET a=a+1 WHERE c=-3; 1806cda207fSdan} { 1816cda207fSdan UPDATE abc SET a=a+1 WHERE c=-3; 1826cda207fSdan UPDATE abc SET a=a+1 WHERE c=-3; 1836cda207fSdan} { 1846cda207fSdan INSERT INTO abc VALUES('one', 'two', 'three'); 1856cda207fSdan} { 1866cda207fSdan SELECT indirect(1); 1876cda207fSdan UPDATE abc SET a='one point five' WHERE c = 'three'; 1886cda207fSdan} { 1896cda207fSdan SELECT indirect(0); 1906cda207fSdan UPDATE abc SET a='one point six' WHERE c = 'three'; 191b08a1efaSdan} { 192b08a1efaSdan CREATE TABLE x1(a, b, PRIMARY KEY(a)); 193b08a1efaSdan SELECT indirect(1); 194b08a1efaSdan INSERT INTO x1 VALUES(1, 2); 195b08a1efaSdan} { 196b08a1efaSdan SELECT indirect(1); 197b08a1efaSdan UPDATE x1 SET b = 3 WHERE a = 1; 1986cda207fSdan} 1996cda207fSdan 2001756ae10Sdancatch {db close} 2011756ae10Sdanforcedelete test.db 2021756ae10Sdansqlite3 db test.db 2031756ae10Sdando_concat_test 2.2 { 2041756ae10Sdan CREATE TABLE t1(a, b, PRIMARY KEY(b)); 2051756ae10Sdan CREATE TABLE t2(a PRIMARY KEY, b); 2061756ae10Sdan INSERT INTO t1 VALUES('string', 1); 2071756ae10Sdan INSERT INTO t1 VALUES(4, 2); 2081756ae10Sdan INSERT INTO t1 VALUES(X'FFAAFFAAFFAA', 3); 2091756ae10Sdan} { 2101756ae10Sdan INSERT INTO t2 VALUES('one', 'two'); 2111756ae10Sdan INSERT INTO t2 VALUES(1, NULL); 2121756ae10Sdan UPDATE t1 SET a = 5 WHERE a = 2; 2131756ae10Sdan} { 2141756ae10Sdan DELETE FROM t2 WHERE a = 1; 2151756ae10Sdan UPDATE t1 SET a = 4 WHERE a = 2; 2161756ae10Sdan INSERT INTO t2 VALUES('x', 'y'); 2171756ae10Sdan} 2181756ae10Sdan 219b08a1efaSdando_test 2.3.0 { 220b08a1efaSdan catch {db close} 221b08a1efaSdan forcedelete test.db 222b08a1efaSdan sqlite3 db test.db 223b08a1efaSdan 224b08a1efaSdan set sql1 "" 225b08a1efaSdan set sql2 "" 226b08a1efaSdan for {set i 1} {$i < 120} {incr i} { 227b08a1efaSdan append sql1 "INSERT INTO x1 VALUES($i*4, $i);" 228b08a1efaSdan } 229b08a1efaSdan for {set i 1} {$i < 120} {incr i} { 230b08a1efaSdan append sql2 "DELETE FROM x1 WHERE a = $i*4;" 231b08a1efaSdan } 232b08a1efaSdan set {} {} 233b08a1efaSdan} {} 234b08a1efaSdando_concat_test 2.3 { 235b08a1efaSdan CREATE TABLE x1(a PRIMARY KEY, b) 236b08a1efaSdan} $sql1 $sql2 $sql1 $sql2 237b08a1efaSdan 238b08a1efaSdando_concat_test 2.4 { 239b08a1efaSdan CREATE TABLE x2(a PRIMARY KEY, b); 240b08a1efaSdan CREATE TABLE x3(a PRIMARY KEY, b); 241b08a1efaSdan 242b08a1efaSdan INSERT INTO x2 VALUES('a', 'b'); 243b08a1efaSdan INSERT INTO x2 VALUES('x', 'y'); 244b08a1efaSdan INSERT INTO x3 VALUES('a', 'b'); 245b08a1efaSdan} { 246b08a1efaSdan INSERT INTO x2 VALUES('c', 'd'); 247b08a1efaSdan INSERT INTO x3 VALUES('e', 'f'); 248b08a1efaSdan INSERT INTO x3 VALUES('x', 'y'); 249b08a1efaSdan} 250b08a1efaSdan 251b08a1efaSdando_concat_test 2.5 { 252b08a1efaSdan UPDATE x3 SET b = 'Y' WHERE a = 'x' 253b08a1efaSdan} { 254b08a1efaSdan DELETE FROM x3 WHERE a = 'x' 255b08a1efaSdan} { 256b08a1efaSdan DELETE FROM x2 WHERE a = 'a' 257b08a1efaSdan} { 258b08a1efaSdan INSERT INTO x2 VALUES('a', 'B'); 259b08a1efaSdan} 260b08a1efaSdan 261*6734007dSdanfor {set k 1} {$k <=10} {incr k} { 262*6734007dSdan do_test 2.6.$k.1 { 263*6734007dSdan drop_all_tables 264*6734007dSdan set sql1 "" 265*6734007dSdan set sql2 "" 266*6734007dSdan for {set i 1} {$i < 120} {incr i} { 267*6734007dSdan append sql1 "INSERT INTO x1 VALUES(randomblob(20+(random()%10)), $i);" 268*6734007dSdan } 269*6734007dSdan for {set i 1} {$i < 120} {incr i} { 270*6734007dSdan append sql2 "DELETE FROM x1 WHERE rowid = $i;" 271*6734007dSdan } 272*6734007dSdan set {} {} 273*6734007dSdan } {} 274*6734007dSdan do_concat_test 2.6.$k { 275*6734007dSdan CREATE TABLE x1(a PRIMARY KEY, b) 276*6734007dSdan } $sql1 $sql2 $sql1 $sql2 277*6734007dSdan} 278*6734007dSdan 279*6734007dSdanfor {set k 1} {$k <=10} {incr k} { 280*6734007dSdan do_test 2.7.$k.1 { 281*6734007dSdan drop_all_tables 282*6734007dSdan set sql1 "" 283*6734007dSdan set sql2 "" 284*6734007dSdan for {set i 1} {$i < 120} {incr i} { 285*6734007dSdan append sql1 { 286*6734007dSdan INSERT INTO x1 VALUES( 287*6734007dSdan CASE WHEN random()%2 THEN random() ELSE randomblob(20+random()%10) END, 288*6734007dSdan CASE WHEN random()%2 THEN random() ELSE randomblob(20+random()%10) END 289*6734007dSdan ); 290*6734007dSdan } 291*6734007dSdan } 292*6734007dSdan for {set i 1} {$i < 120} {incr i} { 293*6734007dSdan append sql2 "DELETE FROM x1 WHERE rowid = $i;" 294*6734007dSdan } 295*6734007dSdan set {} {} 296*6734007dSdan } {} 297*6734007dSdan do_concat_test 2.7.$k { 298*6734007dSdan CREATE TABLE x1(a PRIMARY KEY, b) 299*6734007dSdan } $sql1 $sql2 $sql1 $sql2 300*6734007dSdan} 301*6734007dSdan 302b08a1efaSdan 303f29123b5Sdan#------------------------------------------------------------------------- 304f29123b5Sdan# Test that schema incompatibilities are detected correctly. 305f29123b5Sdan# 306f29123b5Sdan# session5-3.1: Incompatible number of columns. 307f29123b5Sdan# session5-3.2: Incompatible PK definition. 308f29123b5Sdan# 309f29123b5Sdan 310f29123b5Sdando_test 3.1 { 311f29123b5Sdan db close 312f29123b5Sdan forcedelete test.db 313f29123b5Sdan sqlite3 db test.db 314f29123b5Sdan 315f29123b5Sdan execsql { CREATE TABLE t1(a PRIMARY KEY, b) } 3161756ae10Sdan set c1 [changeset_from_sql { INSERT INTO t1 VALUES(1, 2) }] 317f29123b5Sdan execsql { 318f29123b5Sdan DROP TABLE t1; 319f29123b5Sdan CREATE TABLE t1(a PRIMARY KEY, b, c); 320f29123b5Sdan } 3211756ae10Sdan set c2 [changeset_from_sql { INSERT INTO t1 VALUES(2, 3, 4) }] 322f29123b5Sdan 323f29123b5Sdan list [catch { sqlite3changeset_concat $c1 $c2 } msg] $msg 324f29123b5Sdan} {1 SQLITE_SCHEMA} 325f29123b5Sdan 326f29123b5Sdando_test 3.2 { 327f29123b5Sdan db close 328f29123b5Sdan forcedelete test.db 329f29123b5Sdan sqlite3 db test.db 330f29123b5Sdan 331f29123b5Sdan execsql { CREATE TABLE t1(a PRIMARY KEY, b) } 3321756ae10Sdan set c1 [changeset_from_sql { INSERT INTO t1 VALUES(1, 2) }] 333f29123b5Sdan execsql { 334f29123b5Sdan DROP TABLE t1; 335f29123b5Sdan CREATE TABLE t1(a, b PRIMARY KEY); 336f29123b5Sdan } 3371756ae10Sdan set c2 [changeset_from_sql { INSERT INTO t1 VALUES(2, 3) }] 338f29123b5Sdan 339f29123b5Sdan list [catch { sqlite3changeset_concat $c1 $c2 } msg] $msg 340f29123b5Sdan} {1 SQLITE_SCHEMA} 341f29123b5Sdan 342*6734007dSdan#------------------------------------------------------------------------- 343*6734007dSdan# Test that concat() handles these properly: 344*6734007dSdan# 345*6734007dSdan# session5-4.1: INSERT + INSERT 346*6734007dSdan# session5-4.2: UPDATE + INSERT 347*6734007dSdan# session5-4.3: DELETE + UPDATE 348*6734007dSdan# session5-4.4: DELETE + DELETE 349*6734007dSdan# 350*6734007dSdan 351*6734007dSdanproc do_concat_test2 {tn sql1 sqlX sql2 expected} { 352*6734007dSdan sqlite3session S db main ; S attach * 353*6734007dSdan execsql $sql1 354*6734007dSdan set ::c1 [S changeset] 355*6734007dSdan S delete 356*6734007dSdan 357*6734007dSdan execsql $sqlX 358*6734007dSdan 359*6734007dSdan sqlite3session S db main ; S attach * 360*6734007dSdan execsql $sql2 361*6734007dSdan set ::c2 [S changeset] 362*6734007dSdan S delete 363*6734007dSdan 364*6734007dSdan uplevel do_test $tn [list { 365*6734007dSdan changeset_to_list [sqlite3changeset_concat $::c1 $::c2] 366*6734007dSdan }] [list [normalize_list $expected]] 367*6734007dSdan} 368*6734007dSdan 369*6734007dSdandrop_all_tables db 370*6734007dSdando_concat_test2 4.1 { 371*6734007dSdan CREATE TABLE t1(a PRIMARY KEY, b); 372*6734007dSdan INSERT INTO t1 VALUES('key', 'value'); 373*6734007dSdan} { 374*6734007dSdan DELETE FROM t1 WHERE a = 'key'; 375*6734007dSdan} { 376*6734007dSdan INSERT INTO t1 VALUES('key', 'xxx'); 377*6734007dSdan} { 378*6734007dSdan {INSERT t1 0 X. {} {t key t value}} 379*6734007dSdan} 380*6734007dSdando_concat_test2 4.2 { 381*6734007dSdan UPDATE t1 SET b = 'yyy'; 382*6734007dSdan} { 383*6734007dSdan DELETE FROM t1 WHERE a = 'key'; 384*6734007dSdan} { 385*6734007dSdan INSERT INTO t1 VALUES('key', 'value'); 386*6734007dSdan} { 387*6734007dSdan {UPDATE t1 0 X. {t key t xxx} {{} {} t yyy}} 388*6734007dSdan} 389*6734007dSdando_concat_test2 4.3 { 390*6734007dSdan DELETE FROM t1 WHERE a = 'key'; 391*6734007dSdan} { 392*6734007dSdan INSERT INTO t1 VALUES('key', 'www'); 393*6734007dSdan} { 394*6734007dSdan UPDATE t1 SET b = 'valueX' WHERE a = 'key'; 395*6734007dSdan} { 396*6734007dSdan {DELETE t1 0 X. {t key t value} {}} 397*6734007dSdan} 398*6734007dSdando_concat_test2 4.4 { 399*6734007dSdan DELETE FROM t1 WHERE a = 'key'; 400*6734007dSdan} { 401*6734007dSdan INSERT INTO t1 VALUES('key', 'ttt'); 402*6734007dSdan} { 403*6734007dSdan DELETE FROM t1 WHERE a = 'key'; 404*6734007dSdan} { 405*6734007dSdan {DELETE t1 0 X. {t key t valueX} {}} 406*6734007dSdan} 407f29123b5Sdan 4085d607a6eSdanfinish_test 409