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 if_no_rbu_support { finish_test ; return }
15 set ::testprefix rbuprogress
18 proc create_db_file {filename sql} {
20 sqlite3 tmpdb $filename
25 # Create a simple RBU database. That expects to write to a table:
27 # CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
29 proc create_rbu1 {filename} {
30 create_db_file $filename {
31 CREATE TABLE data_t1(a, b, c, rbu_control);
32 INSERT INTO data_t1 VALUES(1, 2, 3, 0);
33 INSERT INTO data_t1 VALUES(2, 'two', 'three', 0);
34 INSERT INTO data_t1 VALUES(3, NULL, 8.2, 0);
36 CREATE TABLE rbu_count(tbl, cnt);
37 INSERT INTO rbu_count VALUES('data_t1', 3);
44 PRAGMA page_size = 4096;
45 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
50 sqlite3rbu rbu test.db rbu.db
53 do_test 1.2 { rbu step ; rbu bp_progress } {3333 0}
54 do_test 1.3 { rbu step ; rbu bp_progress } {6666 0}
55 do_test 1.4 { rbu step ; rbu bp_progress } {10000 0}
56 do_test 1.5 { rbu step ; rbu bp_progress } {10000 0}
57 do_test 1.6 { rbu step ; rbu bp_progress } {10000 0}
58 do_test 1.7 { rbu step ; rbu bp_progress } {10000 5000}
59 do_test 1.8 { rbu step ; rbu bp_progress } {10000 10000}
60 do_test 1.9 { rbu step ; rbu bp_progress } {10000 10000}
66 #-------------------------------------------------------------------------
68 proc do_sp_test {tn bReopen target rbu reslist} {
69 uplevel [list do_test $tn [subst -nocommands {
70 if {$bReopen==0} { sqlite3rbu rbu $target $rbu }
73 if {$bReopen} { sqlite3rbu rbu $target $rbu }
75 if {[set rc] != "SQLITE_OK"} { rbu close ; error "error 1" }
76 lappend res [lindex [rbu bp_progress] 0]
77 if {[lindex [set res] end]==10000} break
78 if {$bReopen} { rbu close }
80 if {[set res] != [list $reslist]} {
82 error "1. reslist incorrect (expect=$reslist got=[set res])"
85 # One step to clean up the temporary tables used to update the only
86 # target table in the rbu database. And one more to move the *-oal
87 # file to *-wal. After each of these steps, the progress remains
90 if {[lindex [list $reslist] 0]!=-1} {
92 set res [rbu bp_progress]
93 if {[set res] != [list 10000 0]} {
95 error "2. reslist incorrect (expect=10000 0 got=[set res])"
100 set res [rbu bp_progress]
101 if {[set res] != [list 10000 0]} {
103 error "3. reslist incorrect (expect=10000 0 got=[set res])"
107 while {[rbu step]=="SQLITE_OK"} {
108 foreach {a b} [rbu bp_progress] {}
109 if {[set a]!=10000 || [set b]<=0 || [set b]>10000} {
111 error "4. reslist incorrect (expect=10000 1..10000 got=[set a] [set b])"
115 set res [rbu bp_progress]
116 if {[set res] != [list 10000 10000]} {
118 error "5. reslist is incorrect (expect=10000 10000 got=[set res])"
125 foreach {bReopen} { 0 1 } {
127 do_test 2.$bReopen.1.0 {
129 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
131 create_db_file rbu.db {
132 CREATE TABLE data_t1(a, b, c, rbu_control);
133 INSERT INTO data_t1 VALUES(4, 4, 4, 0);
134 INSERT INTO data_t1 VALUES(5, 5, 5, 0);
136 CREATE TABLE rbu_count(tbl, cnt);
137 INSERT INTO rbu_count VALUES('data_t1', 2);
140 do_sp_test 2.$bReopen.1.1 $bReopen test.db rbu.db {5000 10000}
143 do_test 2.$bReopen.2.0 {
144 execsql { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c) }
147 do_sp_test 2.$bReopen.2.1 $bReopen test.db rbu.db {3333 6666 10000}
150 do_test 2.$bReopen.3.0 {
152 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
153 CREATE INDEX i1 ON t1(b);
154 INSERT INTO t1 VALUES(1, 1, 1);
155 INSERT INTO t1 VALUES(2, 2, 2);
156 INSERT INTO t1 VALUES(3, 3, 3);
158 create_db_file rbu.db {
159 CREATE TABLE data_t1(a, b, c, rbu_control);
160 INSERT INTO data_t1 VALUES(4, 4, 4, 0);
161 INSERT INTO data_t1 VALUES(2, NULL, NULL, 1);
162 INSERT INTO data_t1 VALUES(5, NULL, NULL, 1);
164 CREATE TABLE rbu_count(tbl, cnt);
165 INSERT INTO rbu_count VALUES('data_t1', 3);
168 do_sp_test 2.$bReopen.3.1 $bReopen test.db rbu.db {1666 3333 6000 8000 10000}
171 do_test 2.$bReopen.4.0 {
173 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
174 CREATE INDEX i1 ON t1(b);
175 INSERT INTO t1 VALUES(1, 1, 1);
176 INSERT INTO t1 VALUES(2, 2, 2);
177 INSERT INTO t1 VALUES(3, 3, 3);
179 create_db_file rbu.db {
180 CREATE TABLE data_t1(a, b, c, rbu_control);
181 INSERT INTO data_t1 VALUES(2, 4, 4, '.xx');
183 CREATE TABLE rbu_count(tbl, cnt);
184 INSERT INTO rbu_count VALUES('data_t1', 1);
187 do_sp_test 2.$bReopen.4.1 $bReopen test.db rbu.db {3333 6666 10000}
190 do_test 2.$bReopen.5.0 {
192 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
193 CREATE INDEX i1 ON t1(b);
194 INSERT INTO t1 VALUES(1, 1, 1);
195 INSERT INTO t1 VALUES(2, 2, 2);
196 INSERT INTO t1 VALUES(3, 3, 3);
198 create_db_file rbu.db {
199 CREATE TABLE data_t1(a, b, c, rbu_control);
200 INSERT INTO data_t1 VALUES(4, NULL, 4, '.xx');
202 CREATE TABLE rbu_count(tbl, cnt);
203 INSERT INTO rbu_count VALUES('data_t1', 1);
206 do_sp_test 2.$bReopen.5.1 $bReopen test.db rbu.db {10000}
209 do_test 2.$bReopen.6.0 {
211 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
212 CREATE INDEX i1 ON t1(b);
213 INSERT INTO t1 VALUES(1, 1, 1);
214 INSERT INTO t1 VALUES(2, 2, 2);
215 INSERT INTO t1 VALUES(3, 3, 3);
217 create_db_file rbu.db {
218 CREATE TABLE data_t1(a, b, c, rbu_control);
219 INSERT INTO data_t1 VALUES(4, 4, 4, 0);
220 INSERT INTO data_t1 VALUES(2, NULL, NULL, 1);
221 INSERT INTO data_t1 VALUES(5, NULL, NULL, 1);
224 do_sp_test 2.$bReopen.6.1 $bReopen test.db rbu.db {-1 -1 -1 -1 -1 10000}
227 #-------------------------------------------------------------------------
228 # The following tests verify that the API works when resuming an update
229 # during the incremental checkpoint stage.
231 proc do_phase2_test {tn bReopen target rbu nStep} {
232 uplevel [list do_test $tn [subst -nocommands {
234 # Build the OAL/WAL file:
235 sqlite3rbu rbu $target $rbu
236 while {[lindex [rbu bp_progress] 0]<10000} {
238 if {"SQLITE_OK" != [set rc]} { rbu close }
241 # Clean up the temp tables and move the *-oal file to *-wal.
245 for {set i 0} {[set i] < $nStep} {incr i} {
248 sqlite3rbu rbu $target $rbu
251 set res [rbu bp_progress]
252 set expect [expr (1 + [set i]) * 10000 / $nStep]
253 if {[lindex [set res] 1] != [set expect]} {
254 error "Have [set res], expected 10000 [set expect]"
259 if {[set rc] != "SQLITE_DONE"} {
260 error "Have [set rc], expected SQLITE_DONE"
267 foreach bReopen {0 1} {
268 do_test 3.$bReopen.1.0 {
271 PRAGMA page_size = 4096;
272 CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
273 CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
274 CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
275 CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
277 create_db_file rbu.db {
278 CREATE TABLE data_t1(a, b, rbu_control);
279 CREATE TABLE data_t2(a, b, rbu_control);
280 CREATE TABLE data_t3(a, b, rbu_control);
281 CREATE TABLE data_t4(a, b, rbu_control);
282 INSERT INTO data_t1 VALUES(1, 2, 0);
283 INSERT INTO data_t2 VALUES(1, 2, 0);
284 INSERT INTO data_t3 VALUES(1, 2, 0);
285 INSERT INTO data_t4 VALUES(1, 2, 0);
287 CREATE TABLE rbu_count(tbl, cnt);
288 INSERT INTO rbu_count VALUES('data_t1', 1);
289 INSERT INTO rbu_count VALUES('data_t2', 1);
290 INSERT INTO rbu_count VALUES('data_t3', 1);
291 INSERT INTO rbu_count VALUES('data_t4', 1);
294 do_phase2_test 3.$bReopen.1.1 $bReopen test.db rbu.db 5
298 foreach {bReopen} { 0 1 } {
300 ipk { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c) }
301 wr { CREATE TABLE t1(a INT PRIMARY KEY, b, c) WITHOUT ROWID }
302 pk { CREATE TABLE t1(a INT PRIMARY KEY, b, c) }
305 foreach {tn2 rbusql r1 r3} {
307 CREATE TABLE data0_t1(a, b, c, rbu_control);
308 INSERT INTO data0_t1 VALUES(15, 15, 15, 0);
309 INSERT INTO data0_t1 VALUES(20, 20, 20, 0);
310 CREATE TABLE rbu_count(tbl, cnt);
311 INSERT INTO rbu_count VALUES('data0_t1', 2);
313 {2500 5000 7500 10000}
314 {1666 3333 5000 6666 8333 10000}
317 CREATE TABLE data0_t1(a, b, c, rbu_control);
318 INSERT INTO data0_t1 VALUES(10, 10, 10, 2);
319 CREATE TABLE rbu_count(tbl, cnt);
320 INSERT INTO rbu_count VALUES('data0_t1', 1);
323 {2000 4000 6000 8000 10000}
326 CREATE TABLE data0_t1(a, b, c, rbu_control);
327 INSERT INTO data0_t1 VALUES(7, 7, 7, 2);
328 INSERT INTO data0_t1 VALUES(10, 10, 10, 2);
329 CREATE TABLE rbu_count(tbl, cnt);
330 INSERT INTO rbu_count VALUES('data0_t1', 2);
332 {2500 4000 6000 8000 10000}
333 {1666 2500 3750 5000 6250 7500 8750 10000}
337 reset_db ; execsql $tbl
338 do_test 4.$tn.$bReopen.$tn2.0 {
340 CREATE INDEX t1c ON t1(c);
341 INSERT INTO t1 VALUES(1, 1, 1);
342 INSERT INTO t1 VALUES(5, 5, 5);
343 INSERT INTO t1 VALUES(10, 10, 10);
345 create_db_file rbu.db $rbusql
351 do_sp_test 4.$tn.$bReopen.$tn2.1 $bReopen test.db rbu.db $R($tn)
356 foreach {bReopen} { 0 1 } {
359 CREATE TABLE t1(a, b, c);
360 CREATE INDEX t1c ON t1(c);
363 CREATE VIRTUAL TABLE t1 USING fts5(a, b, c);
367 if {$tn=="vtab"} { ifcapable !fts5 break }
369 foreach {tn2 rbusql r1 r2} {
371 CREATE TABLE data0_t1(a, b, c, rbu_rowid, rbu_control);
372 INSERT INTO data0_t1 VALUES(15, 15, 15, 4, 0);
373 INSERT INTO data0_t1 VALUES(20, 20, 20, 5, 0);
374 CREATE TABLE rbu_count(tbl, cnt);
375 INSERT INTO rbu_count VALUES('data0_t1', 2);
377 {2500 5000 7500 10000}
381 CREATE TABLE data0_t1(rbu_rowid, a, b, c, rbu_control);
382 INSERT INTO data0_t1 VALUES(0, 7, 7, 7, 2);
383 INSERT INTO data0_t1 VALUES(2, 10, 10, 10, 2);
384 CREATE TABLE rbu_count(tbl, cnt);
385 INSERT INTO rbu_count VALUES('data0_t1', 2);
387 {2500 4000 6000 8000 10000}
391 CREATE TABLE data0_t1(rbu_rowid, a, b, c, rbu_control);
392 INSERT INTO data0_t1 VALUES(1, NULL, NULL, NULL, 1);
393 INSERT INTO data0_t1 VALUES(2, NULL, NULL, 7, '..x');
394 CREATE TABLE rbu_count(tbl, cnt);
395 INSERT INTO rbu_count VALUES('data0_t1', 2);
397 {2500 4000 6000 8000 10000}
401 reset_db ; execsql $tbl
402 do_test 5.$tn.$bReopen.$tn2.0 {
404 INSERT INTO t1 VALUES(1, 1, 1);
405 INSERT INTO t1 VALUES(5, 5, 5);
406 INSERT INTO t1 VALUES(10, 10, 10);
408 create_db_file rbu.db $rbusql
413 do_sp_test 5.$tn.$bReopen.$tn2.1 $bReopen test.db rbu.db $R($tn)
418 #-------------------------------------------------------------------------
419 # Test that sqlite3_bp_progress() works with an RBU vacuum if there
420 # is an rbu_count table in the db being vacuumed.
423 do_execsql_test 6.0 {
424 CREATE TABLE t1(a, b, c);
425 CREATE INDEX i1 ON t1(a);
426 CREATE INDEX i2 ON t1(b);
428 SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100
430 INSERT INTO t1 SELECT i, i, i FROM s;
431 CREATE TABLE rbu_count(tbl TEXT PRIMARY KEY, cnt INTEGER) WITHOUT ROWID;
432 INSERT INTO rbu_count VALUES('t1', (SELECT count(*) FROM t1));
433 INSERT INTO rbu_count VALUES('rbu_count', 2);
440 sqlite3rbu_vacuum rbu test.db state.db
441 while {[rbu step]=="SQLITE_OK"} {
442 foreach {a b} [rbu bp_progress] {
443 if {$a > $maxA} { set maxA $a }
444 if {$b > $maxB} { set maxB $b }
447 list [rbu close] $maxA $maxB
448 } {SQLITE_DONE 10000 10000}