adjust test for new attach behavior introduced in upstream check-in a02da71f
[sqlcipher.git] / ext / rbu / rbu5.test
blob2ae69e96526c8aa68714f30ec9b9b93572c28426
1 # 2014 August 30
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 # Test some properties of the pager_rbu_mode and rbu_mode pragmas.
15 source [file join [file dirname [info script]] rbu_common.tcl]
16 if_no_rbu_support { finish_test ; return }
17 set ::testprefix rbu5
20 # Return a list of the primary key columns for table $tbl in the database
21 # opened by database handle $db.
23 proc pkcols {db tbl} {
24   set ret [list]
25   $db eval "PRAGMA table_info = '$tbl'" {
26     if {$pk} { lappend ret $name }
27   }
28   return $ret
31 # Return a list of all columns for table $tbl in the database opened by 
32 # database handle $db.
34 proc allcols {db tbl} {
35   set ret [list]
36   $db eval "PRAGMA table_info = '$tbl'" {
37     lappend ret $name
38   }
39   return $ret
42 # Return a checksum on all tables and data in the main database attached
43 # to database handle $db. It is possible to add indexes without changing
44 # the checksum.
46 proc datacksum {db} {
48   $db eval { SELECT name FROM sqlite_master WHERE type='table' } {
49     append txt $name
50     set cols [list]
51     set order [list]
52     set cnt 0
53     $db eval "PRAGMA table_info = $name" x {
54       lappend cols "quote($x(name))"
55       lappend order [incr cnt]
56     }
57     set cols [join $cols ,]
58     set order [join $order ,]
59     append txt [$db eval "SELECT $cols FROM $name ORDER BY $order"]
60   }
61   return "[string length $txt]-[md5 $txt]"
64 proc ucontrol {args} {
65   set ret ""
66   foreach a $args {
67     if {$a} {
68       append ret .
69     } else {
70       append ret x
71     }
72   }
73   return $ret
76 # Argument $target is the name of an SQLite database file. $sql is an SQL
77 # script containing INSERT, UPDATE and DELETE statements to execute against
78 # it. This command creates an RBU update database in file $rbu that has
79 # the same effect as the script. The target database is not modified by
80 # this command.
82 proc generate_rbu_db {target rbu sql} {
84   forcedelete $rbu
85   forcecopy $target copy.db
87   # Evaluate the SQL script to modify the contents of copy.db.
88   #
89   sqlite3 dbRbu copy.db
90   dbRbu eval $sql
92   dbRbu function ucontrol ucontrol
93   
94   # Evaluate the SQL script to modify the contents of copy.db.
95   set ret [datacksum dbRbu]
97   dbRbu eval { ATTACH $rbu AS rbu }
98   dbRbu eval { ATTACH $target AS orig }
100   dbRbu eval { SELECT name AS tbl FROM sqlite_master WHERE type = 'table' } {
101     set pk [pkcols dbRbu $tbl]
102     set cols [allcols dbRbu $tbl]
104     # A WHERE clause to test that the PK columns match.
105     #
106     set where [list]
107     foreach c $pk { lappend where "main.$tbl.$c IS orig.$tbl.$c" }
108     set where [join $where " AND "]
109     
110     # A WHERE clause to test that all columns match.
111     #
112     set where2 [list]
113     foreach c $cols { lappend where2 "main.$tbl.$c IS orig.$tbl.$c" }
114     set ucontrol "ucontrol([join $where2 ,])"
115     set where2 [join $where2 " AND "]
117     # Create a data_xxx table in the RBU update database.
118     dbRbu eval "
119       CREATE TABLE rbu.data_$tbl AS SELECT *, '' AS rbu_control 
120       FROM main.$tbl LIMIT 0
121     "
123     # Find all new rows INSERTed by the script.
124     dbRbu eval "
125       INSERT INTO rbu.data_$tbl 
126           SELECT *, 0 AS rbu_control FROM main.$tbl
127           WHERE NOT EXISTS (
128             SELECT 1 FROM orig.$tbl WHERE $where
129           )
130     "
131     
132     # Find all old rows DELETEd by the script.
133     dbRbu eval "
134       INSERT INTO rbu.data_$tbl 
135           SELECT *, 1 AS rbu_control FROM orig.$tbl
136           WHERE NOT EXISTS (
137             SELECT 1 FROM main.$tbl WHERE $where
138           )
139     "
140     
141     # Find all rows UPDATEd by the script.
142     set origcols [list]
143     foreach c $cols { lappend origcols "main.$tbl.$c" }
144     set origcols [join $origcols ,]
145     dbRbu eval "
146       INSERT INTO rbu.data_$tbl
147           SELECT $origcols, $ucontrol AS rbu_control 
148           FROM orig.$tbl, main.$tbl
149           WHERE $where AND NOT ($where2)
150     "
152   }
154   dbRbu close
155   forcedelete copy.db
157   return $ret
160 #-------------------------------------------------------------------------
162 do_execsql_test 1.0 {
163   CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
164   CREATE TABLE t2(x, y, z, PRIMARY KEY(y, z)) WITHOUT ROWID;
166   INSERT INTO t1 VALUES(1, 2, 3);
167   INSERT INTO t1 VALUES(2, 4, 6);
168   INSERT INTO t1 VALUES(3, 6, 9);
170   INSERT INTO t2 VALUES(1, 2, 3);
171   INSERT INTO t2 VALUES(2, 4, 6);
172   INSERT INTO t2 VALUES(3, 6, 9);
174 db close
176 set cksum [generate_rbu_db test.db rbu.db {
177   INSERT INTO t1 VALUES(4, 8, 12);
178   DELETE FROM t1 WHERE a = 2;
179   UPDATE t1 SET c = 15 WHERE a=3;
181   INSERT INTO t2 VALUES(4, 8, 12);
182   DELETE FROM t2 WHERE x = 2;
183   UPDATE t2 SET x = 15 WHERE z=9;
186 foreach {tn idx} {
187   1 {
188   }
189   2 {
190     CREATE INDEX i1 ON t1(a, b, c);
191     CREATE INDEX i2 ON t2(x, y, z);
192   }
193 } {
194   foreach cmd {run step} {
195     forcecopy test.db test.db2
196     forcecopy rbu.db rbu.db2
198     sqlite3 db test.db2
199     db eval $idx
201     do_test 1.$tn.$cmd.1 {
202       ${cmd}_rbu test.db2 rbu.db2
203       datacksum db
204     } $cksum
206     do_test 1.$tn.$cmd.2 {
207       db eval { PRAGMA integrity_check } 
208     } {ok}
210     db close
211   }
214 #-------------------------------------------------------------------------
216 reset_db
217 do_execsql_test 2.0 {
218   CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d, e);
219   INSERT INTO t1 VALUES(-750250,'fyetckfaagjkzqjx',-185831,X'FEAD',444258.29);
220   INSERT INTO t1 VALUES(649081,NULL,X'7DF25BF78778',-342324.63,'akvspktocwozo');
221   INSERT INTO t1 VALUES(-133045,-44822.31,X'',287935,NULL);
222   INSERT INTO t1 VALUES(202132,NULL,X'5399','cujsjtspryqeyovcdpz','m');
223   INSERT INTO t1 VALUES(302910,NULL,'dvdhivtfkaedzhdcnn',-717113.41,688487);
224   INSERT INTO t1 VALUES(-582327,X'7A267A',X'7E6B3CFE5CB9','zacuzilrok',-196478);
225   INSERT INTO t1 VALUES(-190462,X'D1A087E7D68D9578','lsmleti',NULL,-928094);
226   INSERT INTO t1 VALUES(-467665,176344.57,-536684.23,828876.22,X'903E');
227   INSERT INTO t1 VALUES(-629138,632630.29,X'28D6',-774501,X'819BBBFC65');
228   INSERT INTO t1 VALUES(-828110,-54379.24,-881121.44,X'',X'8D5A894F0D');
230   CREATE TABLE t2(a PRIMARY KEY, b, c, d, e) WITHOUT ROWID;
231   INSERT INTO t2 VALUES(-65174,X'AC1DBFFE27310F',-194471.08,347988,X'84041BA6F9BDDE86A8');
232   INSERT INTO t2 VALUES('bzbpi',-952693.69,811628.25,NULL,-817434);
233   INSERT INTO t2 VALUES(-643830,NULL,'n',NULL,'dio');
234   INSERT INTO t2 VALUES('rovoenxxj',NULL,'owupbtdcoxxnvg',-119676,X'55431DFA');
235   INSERT INTO t2 VALUES(899770,'jlygdl',X'DBCA4D1A',NULL,-631773);
236   INSERT INTO t2 VALUES(334698.80,NULL,-697585.58,-89277,-817352);
237   INSERT INTO t2 VALUES(X'1A9EB7547A4AAF38','aiprdhkpzdz','anw','szvjbwdvzucybpwwqjt',X'53');
238   INSERT INTO t2 VALUES(713220,NULL,'hfcqhqzjuqplvkum',X'20B076075649DE','fthgpvqdyy');
239   INSERT INTO t2 VALUES(763908,NULL,'xgslzcpvwfknbr',X'75',X'668146');
240   INSERT INTO t2 VALUES(X'E1BA2B6BA27278','wjbpd',NULL,139341,-290086.15);
242 db close
244 set cksum [generate_rbu_db test.db rbu.db {
245 INSERT INTO t2 VALUES(222916.23,'idh',X'472C517405',X'E3',X'7C4F31824669');
246 INSERT INTO t2 VALUES('xcndjwafcoxwxizoktd',-319567.21,NULL,-720906.43,-577170);
247 INSERT INTO t2 VALUES(376369.99,-536058,'yoaiurfqupdscwc',X'29EC8A2542EC3953E9',-740485.22);
248 INSERT INTO t2 VALUES(X'0EFB4DC50693',-175590.83,X'1779E253CAB5B1789E',X'BC6903',NULL);
249 INSERT INTO t2 VALUES(-288299,'hfrp',NULL,528477,730676.77);
250 DELETE FROM t2 WHERE a < -60000;
252 UPDATE t2 SET b = 'pgnnaaoflnw' WHERE a = 'bzbpi';
253 UPDATE t2 SET c = -675583 WHERE a = 'rovoenxxj';
254 UPDATE t2 SET d = X'09CDF2B2C241' WHERE a = 713220;
256 INSERT INTO t1 VALUES(224938,'bmruycvfznhhnfmgqys','fr',854381,789143);
257 INSERT INTO t1 VALUES(-863931,-1386.26,X'2A058540C2FB5C',NULL,X'F9D5990A');
258 INSERT INTO t1 VALUES(673696,X'97301F0AC5735F44B5',X'440C',227999.92,-709599.79);
259 INSERT INTO t1 VALUES(-243640,NULL,-71718.11,X'1EEFEB38',X'8CC7C55D95E142FBA5');
260 INSERT INTO t1 VALUES(275893,X'',375606.30,X'0AF9EC334711FB',-468194);
261 DELETE FROM t1 WHERE a > 200000;
263 UPDATE t1 SET b = 'pgnnaaoflnw' WHERE a = -190462;
264 UPDATE t1 SET c = -675583 WHERE a = -467665;
265 UPDATE t1 SET d = X'09CDF2B2C241' WHERE a = -133045;
269 foreach {tn idx} {
270   1 {
271   }
272   2 {
273     CREATE UNIQUE INDEX i1 ON t1(b, c, d);
274     CREATE UNIQUE INDEX i2 ON t1(d, e, a);
275     CREATE UNIQUE INDEX i3 ON t1(e, d, c, b);
277     CREATE UNIQUE INDEX i4 ON t2(b, c, d);
278     CREATE UNIQUE INDEX i5 ON t2(d, e, a);
279     CREATE UNIQUE INDEX i6 ON t2(e, d, c, b);
280   }
281 } {
282   foreach cmd {run step} {
283     forcecopy test.db test.db2
284     forcecopy rbu.db rbu.db2
286     sqlite3 db test.db2
287     db eval $idx
289     do_test 2.$tn.$cmd.1 {
290       ${cmd}_rbu test.db2 rbu.db2
291       datacksum db
292     } $cksum
294     do_test 2.$tn.$cmd.2 {
295       db eval { PRAGMA integrity_check } 
296     } {ok}
298     db close
299   }
303 finish_test