1# 2018 October 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# 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 sessioninvert 22 23proc iter_invert {C} { 24 set x [list] 25 sqlite3session_foreach -invert c $C { lappend x $c } 26 set x 27} 28 29proc do_invert_test {tn sql {iter {}}} { 30 31 forcecopy test.db test.db2 32 sqlite3 db2 test.db2 33 34 set C [changeset_from_sql $sql] 35 36 forcecopy test.db test.db3 37 sqlite3 db3 test.db3 38 uplevel [list do_test $tn.1 [list compare_db db db3] {}] 39 40 set I [sqlite3changeset_invert $C] 41 sqlite3changeset_apply db $I {} 42 uplevel [list do_test $tn.2 [list compare_db db db2] {}] 43 44 sqlite3changeset_apply_v2 -invert db3 $C {} 45 uplevel [list do_test $tn.3 [list compare_db db db3] {}] 46 47 if {$iter!=""} { 48 uplevel [list do_test $tn.4 [list iter_invert $C] [list {*}$iter]] 49 } 50 51 catch { db2 close } 52 catch { db3 close } 53} 54 55do_execsql_test 1.0 { 56 CREATE TABLE t1(a PRIMARY KEY, b, c); 57 CREATE TABLE t2(d, e, f, PRIMARY KEY(e, f)); 58 59 INSERT INTO t1 VALUES(1, 'one', 'i'); 60 INSERT INTO t1 VALUES(2, 'two', 'ii'); 61 INSERT INTO t1 VALUES(3, 'three', 'iii'); 62 INSERT INTO t1 VALUES(4, 'four', 'iv'); 63 INSERT INTO t1 VALUES(5, 'five', 'v'); 64 INSERT INTO t1 VALUES(6, 'six', 'vi'); 65 66 INSERT INTO t2 SELECT * FROM t1; 67} 68 69do_invert_test 1.1 { 70 INSERT INTO t1 VALUES(7, 'seven', 'vii'); 71} { 72 {DELETE t1 0 X.. {i 7 t seven t vii} {}} 73} 74 75do_invert_test 1.2 { 76 DELETE FROM t1 WHERE a<4; 77} { 78 {INSERT t1 0 X.. {} {i 1 t one t i}} 79 {INSERT t1 0 X.. {} {i 2 t two t ii}} 80 {INSERT t1 0 X.. {} {i 3 t three t iii}} 81} 82 83do_invert_test 1.3 { 84 UPDATE t1 SET c=5; 85} { 86 {UPDATE t1 0 X.. {i 1 {} {} i 5} {{} {} {} {} t i}} 87 {UPDATE t1 0 X.. {i 2 {} {} i 5} {{} {} {} {} t ii}} 88 {UPDATE t1 0 X.. {i 3 {} {} i 5} {{} {} {} {} t iii}} 89 {UPDATE t1 0 X.. {i 4 {} {} i 5} {{} {} {} {} t iv}} 90 {UPDATE t1 0 X.. {i 5 {} {} i 5} {{} {} {} {} t v}} 91 {UPDATE t1 0 X.. {i 6 {} {} i 5} {{} {} {} {} t vi}} 92} 93 94do_invert_test 1.4 { 95 UPDATE t1 SET b = a+1 WHERE a%2; 96 DELETE FROM t2; 97 INSERT INTO t1 VALUES(10, 'ten', NULL); 98} 99 100do_invert_test 1.5 { 101 UPDATE t2 SET d = d-1; 102} { 103 {UPDATE t2 0 .XX {i 2 t three t iii} {i 3 {} {} {} {}}} 104 {UPDATE t2 0 .XX {i 1 t two t ii} {i 2 {} {} {} {}}} 105 {UPDATE t2 0 .XX {i 5 t six t vi} {i 6 {} {} {} {}}} 106 {UPDATE t2 0 .XX {i 3 t four t iv} {i 4 {} {} {} {}}} 107 {UPDATE t2 0 .XX {i 0 t one t i} {i 1 {} {} {} {}}} 108 {UPDATE t2 0 .XX {i 4 t five t v} {i 5 {} {} {} {}}} 109} 110 111do_execsql_test 2.0 { 112 ANALYZE; 113 PRAGMA writable_schema = 1; 114 DROP TABLE IF EXISTS sqlite_stat4; 115 SELECT * FROM sqlite_stat1; 116} { 117 t2 sqlite_autoindex_t2_1 {6 1 1} 118 t1 sqlite_autoindex_t1_1 {6 1} 119} 120 121do_invert_test 2.1 { 122 INSERT INTO sqlite_stat1 VALUES('t3', 'idx2', '1 2 3'); 123} { 124 {DELETE sqlite_stat1 0 XX. {t t3 t idx2 t {1 2 3}} {}} 125} 126 127do_invert_test 2.2 { 128 DELETE FROM sqlite_stat1; 129} { 130 {INSERT sqlite_stat1 0 XX. {} {t t1 t sqlite_autoindex_t1_1 t {6 1}}} 131 {INSERT sqlite_stat1 0 XX. {} {t t2 t sqlite_autoindex_t2_1 t {6 1 1}}} 132} 133 134do_invert_test 2.3 { 135 UPDATE sqlite_stat1 SET stat = 'hello world'; 136} 137 138do_test 3.0 { 139 forcecopy test.db test.db2 140 sqlite3 db2 test.db2 141 set P [patchset_from_sql { 142 INSERT INTO t2 VALUES(1, 2, 3); 143 DELETE FROM t2 WHERE d = 3; 144 }] 145 146 list [catch { sqlite3changeset_apply_v2 -invert db2 $P {} } msg] $msg 147} {1 SQLITE_CORRUPT} 148 149do_test 3.1 { 150 list [catch { sqlite3session_foreach -invert db2 $P {} } msg] $msg 151} {1 SQLITE_CORRUPT} 152 153do_test 3.2 { 154 sqlite3changeset_apply_v2 db2 $P {} 155 compare_db db db2 156} {} 157 158#------------------------------------------------------------------------- 159# 160reset_db 161do_execsql_test 4.0 { 162 CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE); 163 INSERT INTO t1 VALUES(1, 'one'); 164 INSERT INTO t1 VALUES(2, 'two'); 165 INSERT INTO t1 VALUES(3, 'three'); 166 INSERT INTO t1 VALUES(4, 'four'); 167} 168 169do_invert_test 4.1 { 170 DELETE FROM t1; 171 INSERT INTO t1 VALUES(1, 'two'); 172 INSERT INTO t1 VALUES(2, 'five'); 173 INSERT INTO t1 VALUES(3, 'one'); 174 INSERT INTO t1 VALUES(4, 'three'); 175} { 176 {UPDATE t1 0 X. {i 1 t two} {{} {} t one}} 177 {UPDATE t1 0 X. {i 2 t five} {{} {} t two}} 178 {UPDATE t1 0 X. {i 3 t one} {{} {} t three}} 179 {UPDATE t1 0 X. {i 4 t three} {{} {} t four}} 180} 181 182 183finish_test 184