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 #***********************************************************************
11 # This file implements regression tests for SQLite library. The
12 # focus of this file is testing that the current version of SQLite
13 # is capable of reading and writing databases created by previous
14 # versions, and vice-versa.
16 # To use this test, old versions of the testfixture process should be
17 # copied into the working directory alongside the new version. The old
18 # versions should be named "testfixtureXXX" (or testfixtureXXX.exe on
19 # windows), where XXX can be any string.
21 # This test file uses the tcl code for controlling a second testfixture
22 # process located in lock_common.tcl. See the commments in lock_common.tcl
23 # for documentation of the available commands.
26 set testdir [file dirname $argv0]
27 source $testdir/tester.tcl
28 source $testdir/lock_common.tcl
29 source $testdir/malloc_common.tcl
30 source $testdir/bc_common.tcl
33 if {"" == [bc_find_binaries backcompat.test]} {
38 proc do_backcompat_test {rv bin1 bin2 script} {
42 if {$bin1 != ""} { set ::bc_chan1 [launch_testfixture $bin1] }
43 set ::bc_chan2 [launch_testfixture $bin2]
46 proc code2 {tcl} { uplevel #0 $tcl }
47 if {$bin1 != ""} { proc code2 {tcl} { testfixture $::bc_chan1 $tcl } }
48 proc code1 {tcl} { testfixture $::bc_chan2 $tcl }
50 proc code1 {tcl} { uplevel #0 $tcl }
51 if {$bin1 != ""} { proc code1 {tcl} { testfixture $::bc_chan1 $tcl } }
52 proc code2 {tcl} { testfixture $::bc_chan2 $tcl }
55 proc sql1 sql { code1 [list db eval $sql] }
56 proc sql2 sql { code2 [list db eval $sql] }
58 code1 { sqlite3 db test.db }
59 code2 { sqlite3 db test.db }
61 foreach c {code1 code2} {
63 set v [split [db version] .]
64 if {[llength $v]==3} {lappend v 0}
65 set ::sqlite_libversion [format \
66 "%d%.2d%.2d%.2d" [lindex $v 0] [lindex $v 1] [lindex $v 2] [lindex $v 3]
73 catch { code1 { db close } }
74 catch { code2 { db close } }
75 catch { close $::bc_chan2 }
76 catch { close $::bc_chan1 }
81 array set ::incompatible [list]
82 proc do_allbackcompat_test {script} {
84 foreach bin $::BC(binaries) {
85 set nErr [set_test_counter errors]
89 regsub {.*testfixture\.} $bintag {} bintag
90 set bintag [string map {\.exe {}} $bintag]
91 if {$bintag == ""} {set bintag self}
92 set ::bcname ".$bintag.$dir."
94 rename do_test _do_test
95 proc do_test {nm sql res} {
96 set nm [regsub {\.} $nm $::bcname]
97 uplevel [list _do_test $nm $sql $res]
100 do_backcompat_test $dir {} $bin $script
103 rename _do_test do_test
105 if { $nErr < [set_test_counter errors] } {
106 set ::incompatible([get_version $bin]) 1
111 proc read_file {zFile} {
113 if {[file exists $zFile]} {
115 fconfigure $fd -translation binary -encoding binary
117 if {[file size $zFile]<=$::sqlite_pending_byte || $zFile != "test.db"} {
120 set zData [read $fd $::sqlite_pending_byte]
121 append zData [string repeat x 512]
122 seek $fd [expr $::sqlite_pending_byte+512] start
123 append zData [read $fd]
130 proc write_file {zFile zData} {
131 set fd [open $zFile w]
132 fconfigure $fd -translation binary -encoding binary
133 puts -nonewline $fd $zData
136 proc read_file_system {} {
138 foreach f {test.db test.db-journal test.db-wal} { lappend ret [read_file $f] }
141 proc write_file_system {data} {
142 foreach f {test.db test.db-journal test.db-wal} d $data {
143 if {[string length $d] == 0} {
151 #-------------------------------------------------------------------------
152 # Actual tests begin here.
154 # This first block of tests checks to see that the same database and
155 # journal files can be used by old and new versions. WAL and wal-index
156 # files are tested separately below.
158 do_allbackcompat_test {
160 # Test that database files are backwards compatible.
162 do_test backcompat-1.1.1 { sql1 {
163 CREATE TABLE t1(a PRIMARY KEY, b UNIQUE);
164 INSERT INTO t1 VALUES('abc', 'def');
166 do_test backcompat-1.1.2 { sql2 { SELECT * FROM t1; } } {abc def}
167 do_test backcompat-1.1.3 { sql2 { INSERT INTO t1 VALUES('ghi', 'jkl'); } } {}
168 do_test backcompat-1.1.4 { sql1 { SELECT * FROM t1; } } {abc def ghi jkl}
169 do_test backcompat-1.1.5 { sql1 { PRAGMA integrity_check } } {ok}
170 do_test backcompat-1.1.6 { sql2 { PRAGMA integrity_check } } {ok}
172 # Test that one version can roll back a hot-journal file left in the
173 # file-system by the other version.
175 # Each test case is named "backcompat-1.X...", where X is either 0 or
176 # 1. If it is 0, then the current version creates a journal file that
177 # the old versions try to read. Otherwise, if X is 1, then the old version
178 # creates the journal file and we try to read it with the current version.
180 do_test backcompat-1.2.1 { sql1 {
181 PRAGMA cache_size = 10;
183 INSERT INTO t1 VALUES(randomblob(400), randomblob(400));
184 INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM t1;
185 INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM t1;
186 INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM t1;
187 INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM t1;
190 set cksum1 [sql1 {SELECT md5sum(a), md5sum(b) FROM t1}]
191 set cksum2 [sql2 {SELECT md5sum(a), md5sum(b) FROM t1}]
192 do_test backcompat-1.2.2 [list string compare $cksum1 $cksum2] 0
194 do_test backcompat-1.2.3 { sql1 {
196 UPDATE t1 SET a = randomblob(500);
198 set data [read_file_system]
200 do_test backcompat-1.2.4 { sql1 { COMMIT } } {}
202 set same [expr {[sql2 {SELECT md5sum(a), md5sum(b) FROM t1}] == $cksum2}]
203 do_test backcompat-1.2.5 [list set {} $same] 0
207 write_file_system $data
208 code1 { sqlite3 db test.db }
209 code2 { sqlite3 db test.db }
211 set same [expr {[sql2 {SELECT md5sum(a), md5sum(b) FROM t1}] == $cksum2}]
212 do_test backcompat-1.2.6 [list set {} $same] 1
214 do_test backcompat-1.2.7 { sql1 { PRAGMA integrity_check } } {ok}
215 do_test backcompat-1.2.8 { sql2 { PRAGMA integrity_check } } {ok}
217 do_test backcompat-2.1 {
219 CREATE TABLE t2(a UNIQUE, b PRIMARY KEY, c UNIQUE);
220 INSERT INTO t2 VALUES(1,9,5);
221 INSERT INTO t2 VALUES(5,5,1);
222 INSERT INTO t2 VALUES(9,1,9);
223 SELECT * FROM t2 ORDER BY a;
225 } {1 9 5 5 5 1 9 1 9}
226 do_test backcompat-2.2 {
228 SELECT * FROM sqlite_master WHERE rootpage=-1;
229 SELECT * FROM t2 ORDER BY a;
231 } {1 9 5 5 5 1 9 1 9}
232 do_test backcompat-2.3 {
234 SELECT * FROM t2 ORDER BY b;
236 } {9 1 9 5 5 1 1 9 5}
237 do_test backcompat-2.4 {
239 SELECT * FROM t2 ORDER BY b;
241 } {9 1 9 5 5 1 1 9 5}
242 do_test backcompat-2.5 {
244 SELECT * FROM t2 ORDER BY c;
246 } {5 5 1 1 9 5 9 1 9}
247 do_test backcompat-2.6 {
249 SELECT * FROM t2 ORDER BY c;
251 } {5 5 1 1 9 5 9 1 9}
253 foreach k [lsort [array names ::incompatible]] {
254 puts "ERROR: Detected journal incompatibility with version $k"
259 #-------------------------------------------------------------------------
260 # Test that WAL and wal-index files may be shared between different
263 do_allbackcompat_test {
264 if {[code1 {sqlite3 -version}] >= "3.7.0"
265 && [code1 {set ::sqlite_options(wal)}]
266 && [code2 {sqlite3 -version}] >= "3.7.0"
267 && [code2 {set ::sqlite_options(wal)}]
270 do_test backcompat-2.1.1 { sql1 {
271 PRAGMA journal_mode = WAL;
272 CREATE TABLE t1(a PRIMARY KEY, b UNIQUE);
273 INSERT INTO t1 VALUES('I', 1);
274 INSERT INTO t1 VALUES('II', 2);
275 INSERT INTO t1 VALUES('III', 3);
277 } } {wal I 1 II 2 III 3}
278 do_test backcompat-2.1.2 { sql2 {
282 set data [read_file_system]
285 write_file_system $data
286 code1 {sqlite3 db test.db}
287 code2 {sqlite3 db test.db}
289 # The WAL file now in the file-system was created by the [code1]
290 # process. Check that the [code2] process can recover the log.
292 do_test backcompat-2.1.3 { sql2 {
295 do_test backcompat-2.1.4 { sql1 {
301 #-------------------------------------------------------------------------
302 # Test that FTS3 tables may be read/written by different versions of
307 CREATE VIRTUAL TABLE t1 USING fts3(a, b);
310 one "jk zm jk eczkjblu urvysbnykk sk gnl jk ttvgf hmjf"
311 two "jk bnhc jjrxpjkb mjpavjuhw fibokdry igju jk zm zm xh"
312 three "wxe ogttbykvt uhzq xr iaf zf urvysbnykk aayxpmve oacaxgjoo mjpavjuhw"
313 four "gazrt jk ephknonq myjp uenvbm wuvajhwqz jk zm xnxhf nvfasfh"
314 five "zm aayxpmve csjqxhgj xnxhf xr jk aayxpmve xnxhf zm zm"
315 six "sokcyf zm ogyavjvv jk zm fibokdry zm jk igju igju"
316 seven "vgsld bvgimjik xuprtlyle jk akmikrqyt jk aayxpmve hkfoudzftq ddjj"
317 eight "zm uhzq ovkyevlgv zk uenvbm csjqxhgj jk vgsld pgybs jk"
318 nine "zm agmckuiu zexh fibokdry jk uhzq bu tugflixoex xnxhf sk"
320 append contents "INSERT INTO t1 VALUES('$num', '$doc');"
322 do_allbackcompat_test {
323 if {[code1 {set ::sqlite_options(fts3)}]
324 && [code2 {set ::sqlite_options(fts3)}]
327 do_test backcompat-3.1 { sql1 $contents } {}
330 1 "SELECT * FROM t1 ORDER BY a, b"
331 2 "SELECT rowid FROM t1 WHERE a MATCH 'five'"
332 3 "SELECT * FROM t1 WHERE a MATCH 'five'"
333 4 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'jk'"
334 5 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'tug* OR eight'"
336 do_test backcompat-3.2 [list sql1 $q] [sql2 $q]
339 do_test backcompat-3.3 { sql1 {
340 INSERT INTO t1 SELECT * FROM t1;
341 INSERT INTO t1 SELECT * FROM t1;
342 INSERT INTO t1 SELECT * FROM t1;
343 INSERT INTO t1 SELECT * FROM t1;
344 INSERT INTO t1 SELECT * FROM t1;
345 INSERT INTO t1 SELECT * FROM t1;
346 INSERT INTO t1 SELECT * FROM t1;
347 INSERT INTO t1 SELECT * FROM t1;
351 1 "SELECT * FROM t1 ORDER BY a, b"
352 2 "SELECT rowid FROM t1 WHERE a MATCH 'five'"
353 3 "SELECT * FROM t1 WHERE a MATCH 'five'"
354 4 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'jk'"
355 5 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'tug* OR eight'"
357 do_test backcompat-3.4 [list sql1 $q] [sql2 $q]
360 set alphabet "a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4"
361 for {set i 0} {$i < 900} {incr i} {
362 set term "[lindex $alphabet [expr $i/30]][lindex $alphabet [expr $i%30]] "
363 sql1 "INSERT INTO t1 VALUES($i, '[string repeat $term 14]')"
367 1 "SELECT * FROM t1 ORDER BY a, b"
368 2 "SELECT rowid FROM t1 WHERE a MATCH 'five'"
369 3 "SELECT * FROM t1 WHERE a MATCH 'five'"
370 4 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'jk'"
371 5 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'tug* OR eight'"
373 6 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'aa'"
374 7 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH '44'"
375 8 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'a*'"
377 do_test backcompat-3.5 [list sql1 $q] [sql2 $q]
380 do_test backcompat-3.6 {
381 sql1 "SELECT optimize(t1) FROM t1 LIMIT 1"
382 } {{Index optimized}}
385 1 "SELECT * FROM t1 ORDER BY a, b"
386 2 "SELECT rowid FROM t1 WHERE a MATCH 'five'"
387 3 "SELECT * FROM t1 WHERE a MATCH 'five'"
388 4 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'jk'"
389 5 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'tug* OR eight'"
391 6 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'aa'"
392 7 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH '44'"
393 8 "SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'a*'"
395 do_test backcompat-3.7 [list sql1 $q] [sql2 $q]
398 # Now test that an incremental merge can be started by one version
399 # and finished by another. And that the integrity-check still
401 do_test backcompat-3.8 {
403 DROP TABLE IF EXISTS t1;
404 DROP TABLE IF EXISTS t2;
405 CREATE TABLE t1(docid, words);
406 CREATE VIRTUAL TABLE t2 USING fts3(words);
408 code1 [list source $testdir/genesis.tcl]
409 code1 { fts_kjv_genesis }
411 INSERT INTO t2 SELECT words FROM t1;
412 INSERT INTO t2 SELECT words FROM t1;
413 INSERT INTO t2 SELECT words FROM t1;
414 INSERT INTO t2 SELECT words FROM t1;
415 INSERT INTO t2 SELECT words FROM t1;
416 INSERT INTO t2 SELECT words FROM t1;
417 SELECT level, group_concat(idx, ' ') FROM t2_segdir GROUP BY level;
421 if {[code1 { set ::sqlite_libversion }] >=3071200
422 && [code2 { set ::sqlite_libversion }] >=3071200
424 if {[code1 { set ::sqlite_libversion }]<3120000} {
425 set res {0 {0 1} 1 0}
430 do_test backcompat-3.9 {
431 sql1 { INSERT INTO t2(t2) VALUES('merge=100,4'); }
432 sql2 { INSERT INTO t2(t2) VALUES('merge=100,4'); }
433 sql1 { INSERT INTO t2(t2) VALUES('merge=100,4'); }
434 sql2 { INSERT INTO t2(t2) VALUES('merge=2500,4'); }
436 SELECT level, group_concat(idx, ' ') FROM t2_segdir GROUP BY level;
440 do_test backcompat-3.10 {
441 sql1 { INSERT INTO t2(t2) VALUES('integrity-check') }
442 sql2 { INSERT INTO t2(t2) VALUES('integrity-check') }
449 #-------------------------------------------------------------------------
450 # Test that Rtree tables may be read/written by different versions of
455 CREATE VIRTUAL TABLE t1 USING rtree(id, x1, x2, y1, y2);
457 foreach {id x1 x2 y1 y2} {
458 1 -47.64 43.87 33.86 34.42 2 -21.51 17.32 2.05 31.04
459 3 -43.67 -38.33 -19.79 3.43 4 32.41 35.16 9.12 19.82
460 5 33.28 34.87 14.78 28.26 6 49.31 116.59 -9.87 75.09
461 7 -14.93 34.51 -17.64 64.09 8 -43.05 23.43 -1.19 69.44
462 9 44.79 133.56 28.09 80.30 10 -2.66 81.47 -41.38 -10.46
463 11 -42.89 -3.54 15.76 71.63 12 -3.50 84.96 -11.64 64.95
464 13 -45.69 26.25 11.14 55.06 14 -44.09 11.23 17.52 44.45
465 15 36.23 133.49 -19.38 53.67 16 -17.89 81.54 14.64 50.61
466 17 -41.97 -24.04 -39.43 28.95 18 -5.85 7.76 -6.38 47.02
467 19 18.82 27.10 42.82 100.09 20 39.17 113.45 26.14 73.47
468 21 22.31 103.17 49.92 106.05 22 -43.06 40.38 -1.75 76.08
469 23 2.43 57.27 -14.19 -3.83 24 -47.57 -4.35 8.93 100.06
470 25 -37.47 49.14 -29.11 8.81 26 -7.86 75.72 49.34 107.42
471 27 1.53 45.49 20.36 49.74 28 -48.48 32.54 28.81 54.45
472 29 2.67 39.77 -4.05 13.67 30 4.11 62.88 -47.44 -5.72
473 31 -21.47 51.75 37.25 116.09 32 45.59 111.37 -6.43 43.64
474 33 35.23 48.29 23.54 113.33 34 16.61 68.35 -14.69 65.97
475 35 13.98 16.60 48.66 102.87 36 19.74 23.84 31.15 77.27
476 37 -27.61 24.43 7.96 94.91 38 -34.77 12.05 -22.60 -6.29
477 39 -25.83 8.71 -13.48 -12.53 40 -17.11 -1.01 18.06 67.89
478 41 14.13 71.72 -3.78 39.25 42 23.75 76.00 -16.30 8.23
479 43 -39.15 28.63 38.12 125.88 44 48.62 86.09 36.49 102.95
480 45 -31.39 -21.98 2.52 89.78 46 5.65 56.04 15.94 89.10
481 47 18.28 95.81 46.46 143.08 48 30.93 102.82 -20.08 37.36
482 49 -20.78 -3.48 -5.58 35.46 50 49.85 90.58 -24.48 46.29
484 if {$x1 >= $x2 || $y1 >= $y2} { error "$x1 $x2 $y1 $y2" }
485 append contents "INSERT INTO t1 VALUES($id, $x1, $x2, $y1, $y2);"
488 1 "SELECT id FROM t1 WHERE x1>10 AND x2<44"
489 2 "SELECT id FROM t1 WHERE y1<100"
490 3 "SELECT id FROM t1 WHERE y1<100 AND x1>0"
491 4 "SELECT id FROM t1 WHERE y1>10 AND x1>0 AND x2<50 AND y2<550"
493 do_allbackcompat_test {
494 if {[code1 {set ::sqlite_options(fts3)}]
495 && [code2 {set ::sqlite_options(fts3)}]
498 do_test backcompat-4.1 { sql1 $contents } {}
500 foreach {n q} $::queries {
501 do_test backcompat-4.2.$n [list sql1 $q] [sql2 $q]
504 do_test backcompat-4.3 { sql1 {
505 INSERT INTO t1 SELECT id+100, x1+10.0, x2+10.0, y1-10.0, y2-10.0 FROM t1;
508 foreach {n q} $::queries {
509 do_test backcompat-4.4.$n [list sql1 $q] [sql2 $q]
512 do_test backcompat-4.5 { sql2 {
513 INSERT INTO t1 SELECT id+200, x1+20.0, x2+20.0, y1-20.0, y2-20.0 FROM t1;
516 foreach {n q} $::queries {
517 do_test backcompat-4.6.$n [list sql1 $q] [sql2 $q]