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 |