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 #***********************************************************************
13 source [file join [file dirname [info script]] rbu_common.tcl]
14 set ::testprefix rbuprogress
17 proc create_db_file {filename sql} {
19 sqlite3 tmpdb $filename
24 # Create a simple RBU database. That expects to write to a table:
26 # CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
28 proc create_rbu1 {filename} {
29 create_db_file $filename {
30 CREATE TABLE data_t1(a, b, c, rbu_control);
31 INSERT INTO data_t1 VALUES(1, 2, 3, 0);
32 INSERT INTO data_t1 VALUES(2, 'two', 'three', 0);
33 INSERT INTO data_t1 VALUES(3, NULL, 8.2, 0);
35 CREATE TABLE rbu_count(tbl, cnt);
36 INSERT INTO rbu_count VALUES('data_t1', 3);
43 PRAGMA page_size = 4096;
44 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
49 sqlite3rbu rbu test.db rbu.db
52 do_test 1.2 { rbu step ; rbu bp_progress } {3333 0}
53 do_test 1.3 { rbu step ; rbu bp_progress } {6666 0}
54 do_test 1.4 { rbu step ; rbu bp_progress } {10000 0}
55 do_test 1.5 { rbu step ; rbu bp_progress } {10000 0}
56 do_test 1.6 { rbu step ; rbu bp_progress } {10000 0}
57 do_test 1.7 { rbu step ; rbu bp_progress } {10000 5000}
58 do_test 1.8 { rbu step ; rbu bp_progress } {10000 10000}
59 do_test 1.9 { rbu step ; rbu bp_progress } {10000 10000}
65 #-------------------------------------------------------------------------
67 proc do_sp_test {tn bReopen target rbu reslist} {
68 uplevel [list do_test $tn [subst -nocommands {
69 if {$bReopen==0} { sqlite3rbu rbu $target $rbu }
72 if {$bReopen} { sqlite3rbu rbu $target $rbu }
74 if {[set rc] != "SQLITE_OK"} { rbu close ; error "error 1" }
75 lappend res [lindex [rbu bp_progress] 0]
76 if {[lindex [set res] end]==10000} break
77 if {$bReopen} { rbu close }
79 if {[set res] != [list $reslist]} {
81 error "1. reslist incorrect (expect=$reslist got=[set res])"
84 # One step to clean up the temporary tables used to update the only
85 # target table in the rbu database. And one more to move the *-oal
86 # file to *-wal. After each of these steps, the progress remains
89 if {[lindex [list $reslist] 0]!=-1} {
91 set res [rbu bp_progress]
92 if {[set res] != [list 10000 0]} {
94 error "2. reslist incorrect (expect=10000 0 got=[set res])"
99 set res [rbu bp_progress]
100 if {[set res] != [list 10000 0]} {
102 error "3. reslist incorrect (expect=10000 0 got=[set res])"
106 while {[rbu step]=="SQLITE_OK"} {
107 foreach {a b} [rbu bp_progress] {}
108 if {[set a]!=10000 || [set b]<=0 || [set b]>10000} {
110 error "4. reslist incorrect (expect=10000 1..10000 got=[set a] [set b])"
114 set res [rbu bp_progress]
115 if {[set res] != [list 10000 10000]} {
117 error "5. reslist is incorrect (expect=10000 10000 got=[set res])"
124 foreach {bReopen} { 0 1 } {
126 do_test 2.$bReopen.1.0 {
128 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
130 create_db_file rbu.db {
131 CREATE TABLE data_t1(a, b, c, rbu_control);
132 INSERT INTO data_t1 VALUES(4, 4, 4, 0);
133 INSERT INTO data_t1 VALUES(5, 5, 5, 0);
135 CREATE TABLE rbu_count(tbl, cnt);
136 INSERT INTO rbu_count VALUES('data_t1', 2);
139 do_sp_test 2.$bReopen.1.1 $bReopen test.db rbu.db {5000 10000}
142 do_test 2.$bReopen.2.0 {
143 execsql { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c) }
146 do_sp_test 2.$bReopen.2.1 $bReopen test.db rbu.db {3333 6666 10000}
149 do_test 2.$bReopen.3.0 {
151 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
152 CREATE INDEX i1 ON t1(b);
153 INSERT INTO t1 VALUES(1, 1, 1);
154 INSERT INTO t1 VALUES(2, 2, 2);
155 INSERT INTO t1 VALUES(3, 3, 3);
157 create_db_file rbu.db {
158 CREATE TABLE data_t1(a, b, c, rbu_control);
159 INSERT INTO data_t1 VALUES(4, 4, 4, 0);
160 INSERT INTO data_t1 VALUES(2, NULL, NULL, 1);
161 INSERT INTO data_t1 VALUES(5, NULL, NULL, 1);
163 CREATE TABLE rbu_count(tbl, cnt);
164 INSERT INTO rbu_count VALUES('data_t1', 3);
167 do_sp_test 2.$bReopen.3.1 $bReopen test.db rbu.db {1666 3333 6000 8000 10000}
170 do_test 2.$bReopen.4.0 {
172 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
173 CREATE INDEX i1 ON t1(b);
174 INSERT INTO t1 VALUES(1, 1, 1);
175 INSERT INTO t1 VALUES(2, 2, 2);
176 INSERT INTO t1 VALUES(3, 3, 3);
178 create_db_file rbu.db {
179 CREATE TABLE data_t1(a, b, c, rbu_control);
180 INSERT INTO data_t1 VALUES(2, 4, 4, '.xx');
182 CREATE TABLE rbu_count(tbl, cnt);
183 INSERT INTO rbu_count VALUES('data_t1', 1);
186 do_sp_test 2.$bReopen.4.1 $bReopen test.db rbu.db {3333 6666 10000}
189 do_test 2.$bReopen.5.0 {
191 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
192 CREATE INDEX i1 ON t1(b);
193 INSERT INTO t1 VALUES(1, 1, 1);
194 INSERT INTO t1 VALUES(2, 2, 2);
195 INSERT INTO t1 VALUES(3, 3, 3);
197 create_db_file rbu.db {
198 CREATE TABLE data_t1(a, b, c, rbu_control);
199 INSERT INTO data_t1 VALUES(4, NULL, 4, '.xx');
201 CREATE TABLE rbu_count(tbl, cnt);
202 INSERT INTO rbu_count VALUES('data_t1', 1);
205 do_sp_test 2.$bReopen.5.1 $bReopen test.db rbu.db {10000}
208 do_test 2.$bReopen.6.0 {
210 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
211 CREATE INDEX i1 ON t1(b);
212 INSERT INTO t1 VALUES(1, 1, 1);
213 INSERT INTO t1 VALUES(2, 2, 2);
214 INSERT INTO t1 VALUES(3, 3, 3);
216 create_db_file rbu.db {
217 CREATE TABLE data_t1(a, b, c, rbu_control);
218 INSERT INTO data_t1 VALUES(4, 4, 4, 0);
219 INSERT INTO data_t1 VALUES(2, NULL, NULL, 1);
220 INSERT INTO data_t1 VALUES(5, NULL, NULL, 1);
223 do_sp_test 2.$bReopen.6.1 $bReopen test.db rbu.db {-1 -1 -1 -1 -1 10000}
226 #-------------------------------------------------------------------------
227 # The following tests verify that the API works when resuming an update
228 # during the incremental checkpoint stage.
230 proc do_phase2_test {tn bReopen target rbu nStep} {
231 uplevel [list do_test $tn [subst -nocommands {
233 # Build the OAL/WAL file:
234 sqlite3rbu rbu $target $rbu
235 while {[lindex [rbu bp_progress] 0]<10000} {
237 if {"SQLITE_OK" != [set rc]} { rbu close }
240 # Clean up the temp tables and move the *-oal file to *-wal.
244 for {set i 0} {[set i] < $nStep} {incr i} {
247 sqlite3rbu rbu $target $rbu
250 set res [rbu bp_progress]
251 set expect [expr (1 + [set i]) * 10000 / $nStep]
252 if {[lindex [set res] 1] != [set expect]} {
253 error "Have [set res], expected 10000 [set expect]"
258 if {[set rc] != "SQLITE_DONE"} {
259 error "Have [set rc], expected SQLITE_DONE"
266 foreach bReopen {0 1} {
267 do_test 3.$bReopen.1.0 {
270 PRAGMA page_size = 4096;
271 CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
272 CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
273 CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
274 CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
276 create_db_file rbu.db {
277 CREATE TABLE data_t1(a, b, rbu_control);
278 CREATE TABLE data_t2(a, b, rbu_control);
279 CREATE TABLE data_t3(a, b, rbu_control);
280 CREATE TABLE data_t4(a, b, rbu_control);
281 INSERT INTO data_t1 VALUES(1, 2, 0);
282 INSERT INTO data_t2 VALUES(1, 2, 0);
283 INSERT INTO data_t3 VALUES(1, 2, 0);
284 INSERT INTO data_t4 VALUES(1, 2, 0);
286 CREATE TABLE rbu_count(tbl, cnt);
287 INSERT INTO rbu_count VALUES('data_t1', 1);
288 INSERT INTO rbu_count VALUES('data_t2', 1);
289 INSERT INTO rbu_count VALUES('data_t3', 1);
290 INSERT INTO rbu_count VALUES('data_t4', 1);
293 do_phase2_test 3.$bReopen.1.1 $bReopen test.db rbu.db 5
297 foreach {bReopen} { 0 1 } {
299 ipk { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c) }
300 wr { CREATE TABLE t1(a INT PRIMARY KEY, b, c) WITHOUT ROWID }
301 pk { CREATE TABLE t1(a INT PRIMARY KEY, b, c) }
304 foreach {tn2 rbusql r1 r3} {
306 CREATE TABLE data0_t1(a, b, c, rbu_control);
307 INSERT INTO data0_t1 VALUES(15, 15, 15, 0);
308 INSERT INTO data0_t1 VALUES(20, 20, 20, 0);
309 CREATE TABLE rbu_count(tbl, cnt);
310 INSERT INTO rbu_count VALUES('data0_t1', 2);
312 {2500 5000 7500 10000}
313 {1666 3333 5000 6666 8333 10000}
316 CREATE TABLE data0_t1(a, b, c, rbu_control);
317 INSERT INTO data0_t1 VALUES(10, 10, 10, 2);
318 CREATE TABLE rbu_count(tbl, cnt);
319 INSERT INTO rbu_count VALUES('data0_t1', 1);
322 {2000 4000 6000 8000 10000}
325 CREATE TABLE data0_t1(a, b, c, rbu_control);
326 INSERT INTO data0_t1 VALUES(7, 7, 7, 2);
327 INSERT INTO data0_t1 VALUES(10, 10, 10, 2);
328 CREATE TABLE rbu_count(tbl, cnt);
329 INSERT INTO rbu_count VALUES('data0_t1', 2);
331 {2500 4000 6000 8000 10000}
332 {1666 2500 3750 5000 6250 7500 8750 10000}
336 reset_db ; execsql $tbl
337 do_test 4.$tn.$bReopen.$tn2.0 {
339 CREATE INDEX t1c ON t1(c);
340 INSERT INTO t1 VALUES(1, 1, 1);
341 INSERT INTO t1 VALUES(5, 5, 5);
342 INSERT INTO t1 VALUES(10, 10, 10);
344 create_db_file rbu.db $rbusql
350 do_sp_test 4.$tn.$bReopen.$tn2.1 $bReopen test.db rbu.db $R($tn)
355 foreach {bReopen} { 0 1 } {
358 CREATE TABLE t1(a, b, c);
359 CREATE INDEX t1c ON t1(c);
362 CREATE VIRTUAL TABLE t1 USING fts5(a, b, c);
366 if {$tn=="vtab"} { ifcapable !fts5 break }
368 foreach {tn2 rbusql r1 r2} {
370 CREATE TABLE data0_t1(a, b, c, rbu_rowid, rbu_control);
371 INSERT INTO data0_t1 VALUES(15, 15, 15, 4, 0);
372 INSERT INTO data0_t1 VALUES(20, 20, 20, 5, 0);
373 CREATE TABLE rbu_count(tbl, cnt);
374 INSERT INTO rbu_count VALUES('data0_t1', 2);
376 {2500 5000 7500 10000}
380 CREATE TABLE data0_t1(rbu_rowid, a, b, c, rbu_control);
381 INSERT INTO data0_t1 VALUES(0, 7, 7, 7, 2);
382 INSERT INTO data0_t1 VALUES(2, 10, 10, 10, 2);
383 CREATE TABLE rbu_count(tbl, cnt);
384 INSERT INTO rbu_count VALUES('data0_t1', 2);
386 {2500 4000 6000 8000 10000}
390 CREATE TABLE data0_t1(rbu_rowid, a, b, c, rbu_control);
391 INSERT INTO data0_t1 VALUES(1, NULL, NULL, NULL, 1);
392 INSERT INTO data0_t1 VALUES(2, NULL, NULL, 7, '..x');
393 CREATE TABLE rbu_count(tbl, cnt);
394 INSERT INTO rbu_count VALUES('data0_t1', 2);
396 {2500 4000 6000 8000 10000}
400 reset_db ; execsql $tbl
401 do_test 5.$tn.$bReopen.$tn2.0 {
403 INSERT INTO t1 VALUES(1, 1, 1);
404 INSERT INTO t1 VALUES(5, 5, 5);
405 INSERT INTO t1 VALUES(10, 10, 10);
407 create_db_file rbu.db $rbusql
412 do_sp_test 5.$tn.$bReopen.$tn2.1 $bReopen test.db rbu.db $R($tn)
417 #-------------------------------------------------------------------------
418 # Test that sqlite3_bp_progress() works with an RBU vacuum if there
419 # is an rbu_count table in the db being vacuumed.
422 do_execsql_test 6.0 {
423 CREATE TABLE t1(a, b, c);
424 CREATE INDEX i1 ON t1(a);
425 CREATE INDEX i2 ON t1(b);
427 SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100
429 INSERT INTO t1 SELECT i, i, i FROM s;
430 CREATE TABLE rbu_count(tbl TEXT PRIMARY KEY, cnt INTEGER) WITHOUT ROWID;
431 INSERT INTO rbu_count VALUES('t1', (SELECT count(*) FROM t1));
432 INSERT INTO rbu_count VALUES('rbu_count', 2);
439 sqlite3rbu_vacuum rbu test.db state.db
440 while {[rbu step]=="SQLITE_OK"} {
441 foreach {a b} [rbu bp_progress] {
442 if {$a > $maxA} { set maxA $a }
443 if {$b > $maxB} { set maxB $b }
446 list [rbu close] $maxA $maxB
447 } {SQLITE_DONE 10000 10000}