Snapshot of upstream SQLite 3.41.0
[sqlcipher.git] / ext / rbu / rbudiff.test
blobe5e3df12f266e1bc2dfc3bd9a0c22cd671f54f7f
1 # 2015-07-31
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 #***********************************************************************
12 # Tests for the [sqldiff --rbu] command.
16 source [file join [file dirname [info script]] rbu_common.tcl]
17 if_no_rbu_support { finish_test ; return }
18 set testprefix rbudiff
20 set PROG [test_find_sqldiff]
21 db close
23 proc get_rbudiff_sql {db1 db2} {
24   exec $::PROG --rbu $db1 $db2
27 proc get_vtab_rbudiff_sql {db1 db2} {
28   exec $::PROG --vtab --rbu $db1 $db2
31 proc step_rbu {target rbu} {
32   while 1 {
33     sqlite3rbu rbu $target $rbu
34     set rc [rbu step]
35     rbu close
36     if {$rc != "SQLITE_OK"} break
37   }
38   set rc
41 proc apply_rbudiff {sql target} {
42   test_rbucount $sql
43   forcedelete rbu.db
44   sqlite3 rbudb rbu.db
45   rbudb eval $sql
46   rbudb close
47   step_rbu $target rbu.db
50 proc sqlesc {id} {
51   set ret "'[string map {' ''} $id]'"
52   set ret
55 # The only argument is the output of an [sqldiff -rbu] run. This command
56 # tests that the contents of the rbu_count table is correct. An exception
57 # is thrown if it is not.
59 proc test_rbucount {sql} {
60   sqlite3 tmpdb ""
61   tmpdb eval $sql
62   tmpdb eval {
63     SELECT name FROM sqlite_master WHERE name LIKE 'data%' AND type='table'
64   } {
65     set a [tmpdb eval "SELECT count(*) FROM [sqlesc $name]"]
66     set b [tmpdb eval {SELECT cnt FROM rbu_count WHERE tbl = $name}]
67     if {$a != $b} { 
68       tmpdb close
69       error "rbu_count error - tbl = $name" 
70     }
71   }
72   tmpdb close
73   return ""
76 proc rbudiff_cksum {db1} {
77   set txt ""
79   sqlite3 dbtmp $db1
80   foreach tbl [dbtmp eval {SELECT name FROM sqlite_master WHERE type='table'}] {
81     set cols [list]
82     dbtmp eval "PRAGMA table_info = [sqlesc $tbl]" { 
83       lappend cols "quote( $name )" 
84     }
85     append txt [dbtmp eval \
86       "SELECT [join $cols {||'.'||}] FROM [sqlesc $tbl] ORDER BY 1"
87     ]
88   }
89   dbtmp close
91   md5 $txt
94 foreach {tn init mod} {
95   1 {
96     CREATE TABLE t1(a PRIMARY KEY, b, c);
97     INSERT INTO t1 VALUES(1, 2, 3);
98     INSERT INTO t1 VALUES(4, 5, 6);
99   
100     CREATE TABLE t2(a, b, c, PRIMARY KEY(b, c));
101     INSERT INTO t2 VALUES(1, 2, 3);
102     INSERT INTO t2 VALUES(4, 5, 6);
103   } {
104     INSERT INTO t1 VALUES(7, 8, 9);
105     DELETE FROM t1 WHERE a=4;
106     UPDATE t1 SET c = 11 WHERE a = 1;
107   
108     INSERT INTO t2 VALUES(7, 8, 9);
109     DELETE FROM t2 WHERE a=4;
110     UPDATE t2 SET c = 11 WHERE a = 1;
111   }
113   2 {
114     CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b, c));
115     INSERT INTO t1 VALUES('u', 'v', 'w');
116     INSERT INTO t1 VALUES('x', 'y', 'z');
117   } {
118     DELETE FROM t1 WHERE a='u';
119     INSERT INTO t1 VALUES('a', 'b', 'c');
120   }
122   3 {
123     CREATE TABLE t1(i INTEGER PRIMARY KEY, x);
124     INSERT INTO t1 VALUES(1,
125       X'0000000000000000111111111111111122222222222222223333333333333333'
126     );
127     CREATE TABLE t2(y INTEGER PRIMARY KEY, x);
128     INSERT INTO t2 VALUES(1,
129         X'0000000000000000111111111111111122222222222222223333333333333333'
130     );
131   } {
132     DELETE FROM t1;
133     INSERT INTO t1 VALUES(1,
134       X'0000000000000000111111111111111122222555555552223333333333333333'
135     );
136     DELETE FROM t2;
137     INSERT INTO t2 VALUES(1,
138         X'0000000000000000111111111111111122222222222222223333333FFF333333'
139     );
140   }
142   4 {
143     CREATE TABLE x1(a, b, c, PRIMARY KEY(a, b, c));
144     INSERT INTO x1 VALUES('u', 'v', NULL);
145     INSERT INTO x1 VALUES('x', 'y', 'z');
146     INSERT INTO x1 VALUES('a', NULL, 'b');
147   } {
148     INSERT INTO x1 VALUES('a', 'b', 'c');
149   }
151   5 {
152     CREATE TABLE t1(a PRIMARY KEY, b);
153     INSERT INTO t1 VALUES(1, NULL);
154     INSERT INTO t1 VALUES(2, X'');
155   } {
156     UPDATE t1 SET b = X'' WHERE a=1;
157     UPDATE t1 SET b = NULL WHERE a=2;
158   }
160 } {
161   catch { db close }
163   forcedelete test.db test.db2
164   sqlite3 db test.db
165   db eval "$init"
166   sqlite3 db test.db2
167   db eval "$init ; $mod"
168   db close
170   do_test 1.$tn.2 {
171     set sql [get_rbudiff_sql test.db test.db2]
172     apply_rbudiff $sql test.db
173   } {SQLITE_DONE}
174   do_test 1.$tn.3 { rbudiff_cksum test.db } [rbudiff_cksum test.db2]
176   forcedelete test.db test.db2
177   sqlite3 db test.db
178   db eval "$init ; $mod"
179   sqlite3 db test.db2
180   db eval "$init"
181   db close
183   do_test 1.$tn.4 {
184     set sql [get_rbudiff_sql test.db test.db2]
185     apply_rbudiff $sql test.db
186   } {SQLITE_DONE}
187   do_test 1.$tn.5 { rbudiff_cksum test.db } [rbudiff_cksum test.db2]
190 #-------------------------------------------------------------------------
191 # Test that if the --vtab switch is present, [sqldiff] handles virtual
192 # table types fts[345] and rtree correctly.
194 ifcapable fts3&&fts5&&rtree {
196 foreach {tn init mod} {
197   1 {
198     CREATE VIRTUAL TABLE t1 USING fts5(c);
199     INSERT INTO t1 VALUES('a b c');
200     INSERT INTO t1 VALUES('a b c');
201   } {
202     DELETE FROM t1 WHERE rowid = 1;
203     INSERT INTO t1 VALUES('a b c');
204   }
206   2 {
207     CREATE VIRTUAL TABLE "x y" USING 'rtree'(id, x1, x2);
208     INSERT INTO "x y" VALUES(1, 2, 3);
209     INSERT INTO "x y" VALUES(2, 4, 6);
210   } {
211     DELETE FROM "x y" WHERE rowid = 1;
212     INSERT INTO "x y" VALUES(3, 6, 9);
213   }
215   3 {
216     CREATE VIRTUAL TABLE 'x''y' USING fts3;
217     INSERT INTO 'x''y' VALUES('one two three');
218     INSERT INTO 'x''y' VALUES('four five six');
219   } {
220     DELETE FROM 'x''y' WHERE rowid = 1;
221     INSERT INTO 'x''y' VALUES('one two three');
222   }
223 } {
225   forcedelete test.db test.db2
226   sqlite3 db test.db
227   db eval "$init"
228   sqlite3 db test.db2
229   db eval "$init ; $mod"
230   db close
232   do_test 2.$tn.1 {
233     set sql [get_vtab_rbudiff_sql test.db test.db2]
234     apply_rbudiff $sql test.db
235   } {SQLITE_DONE}
236   do_test 2.$tn.2 { rbudiff_cksum test.db } [rbudiff_cksum test.db2]
241 ifcapable fts5 {
242   foreach {tn init mod} {
243     1 {
244       CREATE VIRTUAL TABLE t1 USING fts5(c);
245       INSERT INTO t1 VALUES('a b c');
246       INSERT INTO t1 VALUES('a b c');
247     } {
248       DELETE FROM t1 WHERE rowid = 1;
249       INSERT INTO t1 VALUES('a b c');
250     }
252     2 {
253       CREATE VIRTUAL TABLE t1 USING FTs5(c);
254       INSERT INTO t1 VALUES('a b c');
255       INSERT INTO t1 VALUES('a b c');
256     } {
257       DELETE FROM t1 WHERE rowid = 1;
258       INSERT INTO t1 VALUES('a b c');
259     }
261     3 {
262       creAte    virTUal
263 tablE t1 USING FTs5(c);
264       INSERT INTO t1 VALUES('a b c');
265       INSERT INTO t1 VALUES('a b c');
266     } {
267       DELETE FROM t1 WHERE rowid = 1;
268       INSERT INTO t1 VALUES('a b c');
269     }
270     4 {
271       creAte virTUal tablE      t1      USING FTs5(c);
272       INSERT INTO t1 VALUES('a b c');
273       INSERT INTO t1 VALUES('a b c');
274     } {
275       DELETE FROM t1 WHERE rowid = 1;
276       INSERT INTO t1 VALUES('a b c');
277     }
279   } {
280     forcedelete test.db test.db2
281     sqlite3 db test.db
282     db eval "$init"
283     sqlite3 db test.db2
284     db eval "$init ; $mod"
285     db eval { INSERT INTO t1(t1) VALUES('optimize') }
286     db close
288     do_test 3.$tn.1 {
289       set sql [get_vtab_rbudiff_sql test.db test.db2]
290       apply_rbudiff $sql test.db
291     } {SQLITE_DONE}
293     sqlite3 db test.db
294     sqlite3 db2 test.db2
295     do_test 3.$tn.2 { 
296       db2 eval { SELECT * FROM t1 ORDER BY rowid }
297     } [db eval { SELECT * FROM t1 ORDER BY rowid }]
299     do_test 3.$tn.3 { 
300       db2 eval { INSERT INTO t1(t1) VALUES('integrity-check') }
301     } {}
303     db close
304     db2 close
305   }
309 finish_test