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