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