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