OLD | NEW |
| (Empty) |
1 # 2007 April 26 | |
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 # This file implements regression tests for SQLite library. The | |
12 # focus of this file is testing the incremental vacuum feature. | |
13 # | |
14 # Note: There are also some tests for incremental vacuum and IO | |
15 # errors in incrvacuum_ioerr.test. | |
16 # | |
17 # $Id: incrvacuum.test,v 1.23 2009/02/18 20:31:18 drh Exp $ | |
18 | |
19 set testdir [file dirname $argv0] | |
20 source $testdir/tester.tcl | |
21 | |
22 # If this build of the library does not support auto-vacuum, omit this | |
23 # whole file. | |
24 ifcapable {!autovacuum || !pragma} { | |
25 finish_test | |
26 return | |
27 } | |
28 | |
29 #--------------------------------------------------------------------- | |
30 # Test the pragma on an empty database. | |
31 # | |
32 do_test incrvacuum-1.1 { | |
33 execsql { | |
34 pragma auto_vacuum; | |
35 } | |
36 } $sqlite_options(default_autovacuum) | |
37 do_test incrvacuum-1.2.0 { | |
38 # File size is sometimes 1 instead of 0 due to the hack we put in | |
39 # to work around ticket #3260. Search for comments on #3260 in | |
40 # os_unix.c. | |
41 expr {[file size test.db] > 1} | |
42 } {0} | |
43 do_test incrvacuum-1.2 { | |
44 # This command will create the database. | |
45 execsql { | |
46 pragma auto_vacuum = 'full'; | |
47 pragma auto_vacuum; | |
48 } | |
49 } {1} | |
50 do_test incrvacuum-1.2.1 { | |
51 expr {[file size test.db] > 0} | |
52 } {1} | |
53 do_test incrvacuum-1.3 { | |
54 execsql { | |
55 pragma auto_vacuum = 'incremental'; | |
56 pragma auto_vacuum; | |
57 } | |
58 } {2} | |
59 do_test incrvacuum-1.4 { | |
60 # In this case the invalid value is ignored and the auto_vacuum | |
61 # setting remains unchanged. | |
62 execsql { | |
63 pragma auto_vacuum = 'invalid'; | |
64 pragma auto_vacuum; | |
65 } | |
66 } {2} | |
67 do_test incrvacuum-1.5 { | |
68 execsql { | |
69 pragma auto_vacuum = 1; | |
70 pragma auto_vacuum; | |
71 } | |
72 } {1} | |
73 do_test incrvacuum-1.6 { | |
74 execsql { | |
75 pragma auto_vacuum = '2'; | |
76 pragma auto_vacuum; | |
77 } | |
78 } {2} | |
79 do_test incrvacuum-1.7 { | |
80 # Invalid value. auto_vacuum setting remains unchanged. | |
81 execsql { | |
82 pragma auto_vacuum = 5; | |
83 pragma auto_vacuum; | |
84 } | |
85 } {2} | |
86 | |
87 #--------------------------------------------------------------------- | |
88 # Test the pragma on a non-empty database. It is possible to toggle | |
89 # the connection between "full" and "incremental" mode, but not to | |
90 # change from either of these to "none", or from "none" to "full" or | |
91 # "incremental". | |
92 # | |
93 do_test incrvacuum-2.1 { | |
94 execsql { | |
95 pragma auto_vacuum = 1; | |
96 CREATE TABLE abc(a, b, c); | |
97 } | |
98 } {} | |
99 do_test incrvacuum-2.2 { | |
100 execsql { | |
101 pragma auto_vacuum = 'none'; | |
102 pragma auto_vacuum; | |
103 } | |
104 } {1} | |
105 do_test incrvacuum-2.2.1 { | |
106 db close | |
107 sqlite3 db test.db | |
108 execsql { | |
109 pragma auto_vacuum; | |
110 } | |
111 } {1} | |
112 do_test incrvacuum-2.3 { | |
113 execsql { | |
114 pragma auto_vacuum = 'incremental'; | |
115 pragma auto_vacuum; | |
116 } | |
117 } {2} | |
118 do_test incrvacuum-2.4 { | |
119 execsql { | |
120 pragma auto_vacuum = 'full'; | |
121 pragma auto_vacuum; | |
122 } | |
123 } {1} | |
124 | |
125 #--------------------------------------------------------------------- | |
126 # Test that when the auto_vacuum mode is "incremental", the database | |
127 # does not shrink when pages are removed from it. But it does if | |
128 # the mode is set to "full". | |
129 # | |
130 do_test incrvacuum-3.1 { | |
131 execsql { | |
132 pragma auto_vacuum; | |
133 } | |
134 } {1} | |
135 do_test incrvacuum-3.2 { | |
136 set ::str [string repeat 1234567890 110] | |
137 execsql { | |
138 PRAGMA auto_vacuum = 2; | |
139 BEGIN; | |
140 CREATE TABLE tbl2(str); | |
141 INSERT INTO tbl2 VALUES($::str); | |
142 COMMIT; | |
143 } | |
144 # 5 pages: | |
145 # | |
146 # 1 -> database header | |
147 # 2 -> first back-pointer page | |
148 # 3 -> table abc | |
149 # 4 -> table tbl2 | |
150 # 5 -> table tbl2 overflow page. | |
151 # | |
152 expr {[file size test.db] / 1024} | |
153 } {5} | |
154 do_test incrvacuum-3.3 { | |
155 execsql { | |
156 DROP TABLE abc; | |
157 DELETE FROM tbl2; | |
158 } | |
159 expr {[file size test.db] / 1024} | |
160 } {5} | |
161 do_test incrvacuum-3.4 { | |
162 execsql { | |
163 PRAGMA auto_vacuum = 1; | |
164 INSERT INTO tbl2 VALUES('hello world'); | |
165 } | |
166 expr {[file size test.db] / 1024} | |
167 } {3} | |
168 | |
169 #--------------------------------------------------------------------- | |
170 # Try to run a very simple incremental vacuum. Also verify that | |
171 # PRAGMA incremental_vacuum is a harmless no-op against a database that | |
172 # does not support auto-vacuum. | |
173 # | |
174 do_test incrvacuum-4.1 { | |
175 set ::str [string repeat 1234567890 110] | |
176 execsql { | |
177 PRAGMA auto_vacuum = 2; | |
178 INSERT INTO tbl2 VALUES($::str); | |
179 CREATE TABLE tbl1(a, b, c); | |
180 } | |
181 expr {[file size test.db] / 1024} | |
182 } {5} | |
183 do_test incrvacuum-4.2 { | |
184 execsql { | |
185 DELETE FROM tbl2; | |
186 DROP TABLE tbl1; | |
187 } | |
188 expr {[file size test.db] / 1024} | |
189 } {5} | |
190 do_test incrvacuum-4.3 { | |
191 set ::nStep 0 | |
192 db eval {pragma incremental_vacuum(10)} { | |
193 incr ::nStep | |
194 } | |
195 list [expr {[file size test.db] / 1024}] $::nStep | |
196 } {3 2} | |
197 | |
198 #--------------------------------------------------------------------- | |
199 # The following tests - incrvacuum-5.* - test incremental vacuum | |
200 # from within a transaction. | |
201 # | |
202 do_test incrvacuum-5.1.1 { | |
203 expr {[file size test.db] / 1024} | |
204 } {3} | |
205 do_test incrvacuum-5.1.2 { | |
206 execsql { | |
207 BEGIN; | |
208 DROP TABLE tbl2; | |
209 PRAGMA incremental_vacuum; | |
210 COMMIT; | |
211 } | |
212 expr {[file size test.db] / 1024} | |
213 } {1} | |
214 | |
215 do_test incrvacuum-5.2.1 { | |
216 set ::str [string repeat abcdefghij 110] | |
217 execsql { | |
218 BEGIN; | |
219 CREATE TABLE tbl1(a); | |
220 INSERT INTO tbl1 VALUES($::str); | |
221 PRAGMA incremental_vacuum; -- this is a no-op. | |
222 COMMIT; | |
223 } | |
224 expr {[file size test.db] / 1024} | |
225 } {4} | |
226 do_test incrvacuum-5.2.2 { | |
227 set ::str [string repeat abcdefghij 110] | |
228 execsql { | |
229 BEGIN; | |
230 INSERT INTO tbl1 VALUES($::str); | |
231 INSERT INTO tbl1 SELECT * FROM tbl1; | |
232 DELETE FROM tbl1 WHERE oid%2; -- Put 2 overflow pages on free-list. | |
233 COMMIT; | |
234 } | |
235 expr {[file size test.db] / 1024} | |
236 } {7} | |
237 do_test incrvacuum-5.2.3 { | |
238 execsql { | |
239 BEGIN; | |
240 PRAGMA incremental_vacuum; -- Vacuum up the two pages. | |
241 CREATE TABLE tbl2(b); -- Use one free page as a table root. | |
242 INSERT INTO tbl2 VALUES('a nice string'); | |
243 COMMIT; | |
244 } | |
245 expr {[file size test.db] / 1024} | |
246 } {6} | |
247 do_test incrvacuum-5.2.4 { | |
248 execsql { | |
249 SELECT * FROM tbl2; | |
250 } | |
251 } {{a nice string}} | |
252 do_test incrvacuum-5.2.5 { | |
253 execsql { | |
254 DROP TABLE tbl1; | |
255 DROP TABLE tbl2; | |
256 PRAGMA incremental_vacuum; | |
257 } | |
258 expr {[file size test.db] / 1024} | |
259 } {1} | |
260 | |
261 | |
262 # Test cases incrvacuum-5.3.* use the following list as input data. | |
263 # Two new databases are opened, one with incremental vacuum enabled, | |
264 # the other with no auto-vacuum completely disabled. After executing | |
265 # each element of the following list on both databases, test that | |
266 # the integrity-check passes and the contents of each are identical. | |
267 # | |
268 set TestScriptList [list { | |
269 BEGIN; | |
270 CREATE TABLE t1(a, b); | |
271 CREATE TABLE t2(a, b); | |
272 CREATE INDEX t1_i ON t1(a); | |
273 CREATE INDEX t2_i ON t2(a); | |
274 } { | |
275 INSERT INTO t1 VALUES($::str1, $::str2); | |
276 INSERT INTO t1 VALUES($::str1||$::str2, $::str2||$::str1); | |
277 INSERT INTO t2 SELECT b, a FROM t1; | |
278 INSERT INTO t2 SELECT a, b FROM t1; | |
279 INSERT INTO t1 SELECT b, a FROM t2; | |
280 UPDATE t2 SET b = ''; | |
281 PRAGMA incremental_vacuum; | |
282 } { | |
283 UPDATE t2 SET b = (SELECT b FROM t1 WHERE t1.oid = t2.oid); | |
284 PRAGMA incremental_vacuum; | |
285 } { | |
286 CREATE TABLE t3(a, b); | |
287 INSERT INTO t3 SELECT * FROM t2; | |
288 DROP TABLE t2; | |
289 PRAGMA incremental_vacuum; | |
290 } { | |
291 CREATE INDEX t3_i ON t3(a); | |
292 COMMIT; | |
293 } { | |
294 BEGIN; | |
295 DROP INDEX t3_i; | |
296 PRAGMA incremental_vacuum; | |
297 INSERT INTO t3 VALUES('hello', 'world'); | |
298 ROLLBACK; | |
299 } { | |
300 INSERT INTO t3 VALUES('hello', 'world'); | |
301 } | |
302 ] | |
303 | |
304 # If this build omits subqueries, step 2 in the above list will not | |
305 # work. Replace it with "" in this case. | |
306 # | |
307 ifcapable !subquery { lset TestScriptList 2 "" } | |
308 | |
309 # Compare the contents of databases $A and $B. | |
310 # | |
311 proc compare_dbs {A B tname} { | |
312 set tbl_list [execsql { | |
313 SELECT tbl_name FROM sqlite_master WHERE type = 'table' | |
314 } $A] | |
315 | |
316 do_test ${tname}.1 [subst { | |
317 execsql { | |
318 SELECT tbl_name FROM sqlite_master WHERE type = 'table' | |
319 } $B | |
320 }] $tbl_list | |
321 | |
322 set tn 1 | |
323 foreach tbl $tbl_list { | |
324 set control [execsql "SELECT * FROM $tbl" $A] | |
325 do_test ${tname}.[incr tn] [subst { | |
326 execsql "SELECT * FROM $tbl" $B | |
327 }] $control | |
328 } | |
329 } | |
330 | |
331 set ::str1 [string repeat abcdefghij 130] | |
332 set ::str2 [string repeat 1234567890 105] | |
333 | |
334 forcedelete test1.db test1.db-journal test2.db test2.db-journal | |
335 sqlite3 db1 test1.db | |
336 sqlite3 db2 test2.db | |
337 execsql { PRAGMA auto_vacuum = 'none' } db1 | |
338 execsql { PRAGMA auto_vacuum = 'incremental' } db2 | |
339 | |
340 set tn 1 | |
341 foreach sql $::TestScriptList { | |
342 execsql $sql db1 | |
343 execsql $sql db2 | |
344 | |
345 compare_dbs db1 db2 incrvacuum-5.3.${tn} | |
346 do_test incrvacuum-5.3.${tn}.integrity1 { | |
347 execsql { PRAGMA integrity_check; } db1 | |
348 } {ok} | |
349 do_test incrvacuum-5.3.${tn}.integrity2 { | |
350 execsql { PRAGMA integrity_check; } db2 | |
351 } {ok} | |
352 incr tn | |
353 } | |
354 db1 close | |
355 db2 close | |
356 # | |
357 # End of test cases 5.3.* | |
358 | |
359 #--------------------------------------------------------------------- | |
360 # The following tests - incrvacuum-6.* - test running incremental | |
361 # vacuum while another statement (a read) is being executed. | |
362 # | |
363 for {set jj 0} {$jj < 10} {incr jj} { | |
364 # Build some test data. Two tables are created in an empty | |
365 # database. tbl1 data is a contiguous block starting at page 5 (pages | |
366 # 3 and 4 are the table roots). tbl2 is a contiguous block starting | |
367 # right after tbl1. | |
368 # | |
369 # Then drop tbl1 so that when an incr vacuum is run the pages | |
370 # of tbl2 have to be moved to fill the gap. | |
371 # | |
372 do_test incrvacuum-6.${jj}.1 { | |
373 execsql { | |
374 DROP TABLE IF EXISTS tbl1; | |
375 DROP TABLE IF EXISTS tbl2; | |
376 PRAGMA incremental_vacuum; | |
377 CREATE TABLE tbl1(a, b); | |
378 CREATE TABLE tbl2(a, b); | |
379 BEGIN; | |
380 } | |
381 for {set ii 0} {$ii < 1000} {incr ii} { | |
382 db eval {INSERT INTO tbl1 VALUES($ii, $ii || $ii)} | |
383 } | |
384 execsql { | |
385 INSERT INTO tbl2 SELECT * FROM tbl1; | |
386 COMMIT; | |
387 DROP TABLE tbl1; | |
388 } | |
389 expr {[file size test.db] / 1024} | |
390 } {36} | |
391 | |
392 # Run a linear scan query on tbl2. After reading ($jj*100) rows, | |
393 # run the incremental vacuum to shrink the database. | |
394 # | |
395 do_test incrvacuum-6.${jj}.2 { | |
396 set ::nRow 0 | |
397 db eval {SELECT a FROM tbl2} {} { | |
398 if {$a == [expr $jj*100]} { | |
399 db eval {PRAGMA incremental_vacuum} | |
400 } | |
401 incr ::nRow | |
402 } | |
403 list [expr {[file size test.db] / 1024}] $nRow | |
404 } {19 1000} | |
405 } | |
406 | |
407 #--------------------------------------------------------------------- | |
408 # This test - incrvacuum-7.* - is to check that the database can be | |
409 # written in the middle of an incremental vacuum. | |
410 # | |
411 set ::iWrite 1 | |
412 while 1 { | |
413 do_test incrvacuum-7.${::iWrite}.1 { | |
414 execsql { | |
415 DROP TABLE IF EXISTS tbl1; | |
416 DROP TABLE IF EXISTS tbl2; | |
417 PRAGMA incremental_vacuum; | |
418 CREATE TABLE tbl1(a, b); | |
419 CREATE TABLE tbl2(a, b); | |
420 BEGIN; | |
421 } | |
422 for {set ii 0} {$ii < 1000} {incr ii} { | |
423 db eval {INSERT INTO tbl1 VALUES($ii, $ii || $ii)} | |
424 } | |
425 execsql { | |
426 INSERT INTO tbl2 SELECT * FROM tbl1; | |
427 COMMIT; | |
428 DROP TABLE tbl1; | |
429 } | |
430 expr {[file size test.db] / 1024} | |
431 } {36} | |
432 | |
433 do_test incrvacuum-7.${::iWrite}.2 { | |
434 set ::nRow 0 | |
435 db eval {PRAGMA incremental_vacuum} { | |
436 incr ::nRow | |
437 if {$::nRow == $::iWrite} { | |
438 db eval { | |
439 CREATE TABLE tbl1(a, b); | |
440 INSERT INTO tbl1 VALUES('hello', 'world'); | |
441 } | |
442 } | |
443 } | |
444 list [expr {[file size test.db] / 1024}] | |
445 } {20} | |
446 | |
447 do_test incrvacuum-7.${::iWrite}.3 { | |
448 execsql { | |
449 SELECT * FROM tbl1; | |
450 } | |
451 } {hello world} | |
452 | |
453 if {$::nRow == $::iWrite} break | |
454 incr ::iWrite | |
455 } | |
456 | |
457 #--------------------------------------------------------------------- | |
458 # This test - incrvacuum-8.* - is to check that nothing goes wrong | |
459 # with an incremental-vacuum if it is the first statement executed | |
460 # after an existing database is opened. | |
461 # | |
462 # At one point, this would always return SQLITE_SCHEMA (which | |
463 # causes an infinite loop in tclsqlite.c if using the Tcl interface). | |
464 # | |
465 do_test incrvacuum-8.1 { | |
466 db close | |
467 sqlite3 db test.db | |
468 execsql { | |
469 PRAGMA incremental_vacuum(50); | |
470 } | |
471 } {} | |
472 | |
473 #--------------------------------------------------------------------- | |
474 # At one point this test case was causing an assert() to fail. | |
475 # | |
476 do_test incrvacuum-9.1 { | |
477 db close | |
478 forcedelete test.db test.db-journal | |
479 sqlite3 db test.db | |
480 | |
481 execsql { | |
482 PRAGMA auto_vacuum = 'incremental'; | |
483 CREATE TABLE t1(a, b, c); | |
484 CREATE TABLE t2(a, b, c); | |
485 INSERT INTO t2 VALUES(randstr(500,500),randstr(500,500),randstr(500,500)); | |
486 INSERT INTO t1 VALUES(1, 2, 3); | |
487 INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1; | |
488 INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1; | |
489 INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1; | |
490 INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1; | |
491 INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1; | |
492 INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1; | |
493 INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1; | |
494 INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1; | |
495 } | |
496 } {} | |
497 | |
498 do_test incrvacuum-9.2 { | |
499 execsql { | |
500 PRAGMA synchronous = 'OFF'; | |
501 BEGIN; | |
502 UPDATE t1 SET a = a, b = b, c = c; | |
503 DROP TABLE t2; | |
504 PRAGMA incremental_vacuum(10); | |
505 ROLLBACK; | |
506 } | |
507 } {} | |
508 | |
509 do_test incrvacuum-9.3 { | |
510 execsql { | |
511 PRAGMA cache_size = 10; | |
512 BEGIN; | |
513 UPDATE t1 SET a = a, b = b, c = c; | |
514 DROP TABLE t2; | |
515 PRAGMA incremental_vacuum(10); | |
516 ROLLBACK; | |
517 } | |
518 } {} | |
519 | |
520 #--------------------------------------------------------------------- | |
521 # Test that the parameter to the incremental_vacuum pragma works. That | |
522 # is, if the user executes "PRAGMA incremental_vacuum(N)", at most | |
523 # N pages are vacuumed. | |
524 # | |
525 do_test incrvacuum-10.1 { | |
526 execsql { | |
527 DROP TABLE t1; | |
528 DROP TABLE t2; | |
529 } | |
530 expr [file size test.db] / 1024 | |
531 } {29} | |
532 | |
533 do_test incrvacuum-10.2 { | |
534 execsql { | |
535 PRAGMA incremental_vacuum(1); | |
536 } | |
537 expr [file size test.db] / 1024 | |
538 } {28} | |
539 | |
540 do_test incrvacuum-10.3 { | |
541 execsql { | |
542 PRAGMA incremental_vacuum(5); | |
543 } | |
544 expr [file size test.db] / 1024 | |
545 } {23} | |
546 | |
547 do_test incrvacuum-10.4 { | |
548 execsql { | |
549 PRAGMA incremental_vacuum('1'); | |
550 } | |
551 expr [file size test.db] / 1024 | |
552 } {22} | |
553 | |
554 do_test incrvacuum-10.5 { | |
555 execsql { | |
556 PRAGMA incremental_vacuum("+3"); | |
557 } | |
558 expr [file size test.db] / 1024 | |
559 } {19} | |
560 | |
561 do_test incrvacuum-10.6 { | |
562 execsql { | |
563 PRAGMA incremental_vacuum = 1; | |
564 } | |
565 expr [file size test.db] / 1024 | |
566 } {18} | |
567 | |
568 do_test incrvacuum-10.7 { | |
569 # Use a really big number as an argument to incremetal_vacuum. Should | |
570 # be interpreted as "free all possible space". | |
571 execsql { | |
572 PRAGMA incremental_vacuum(2147483649); | |
573 } | |
574 expr [file size test.db] / 1024 | |
575 } {1} | |
576 | |
577 do_test incrvacuum-10.8 { | |
578 execsql { | |
579 CREATE TABLE t1(x); | |
580 INSERT INTO t1 VALUES(hex(randomblob(1000))); | |
581 DROP TABLE t1; | |
582 } | |
583 # A negative number means free all possible space. | |
584 execsql { | |
585 PRAGMA incremental_vacuum=-1; | |
586 } | |
587 expr [file size test.db] / 1024 | |
588 } {1} | |
589 | |
590 #---------------------------------------------------------------- | |
591 # Test that if we set the auto_vacuum mode to 'incremental', then | |
592 # create a database, thereafter that database defaults to incremental | |
593 # vacuum mode. | |
594 # | |
595 db close | |
596 forcedelete test.db test.db-journal | |
597 sqlite3 db test.db | |
598 | |
599 ifcapable default_autovacuum { | |
600 do_test incrvacuum-11.1-av-dflt-on { | |
601 execsql { | |
602 PRAGMA auto_vacuum; | |
603 } | |
604 } $AUTOVACUUM | |
605 } else { | |
606 do_test incrvacuum-11.1-av-dflt-off { | |
607 execsql { | |
608 PRAGMA auto_vacuum; | |
609 } | |
610 } {0} | |
611 } | |
612 do_test incrvacuum-11.2 { | |
613 execsql { | |
614 PRAGMA auto_vacuum = incremental; | |
615 } | |
616 } {} | |
617 do_test incrvacuum-11.3 { | |
618 execsql { | |
619 PRAGMA auto_vacuum; | |
620 } | |
621 } {2} | |
622 do_test incrvacuum-11.4 { | |
623 # The database has now been created. | |
624 expr {[file size test.db]>0} | |
625 } {1} | |
626 do_test incrvacuum-11.5 { | |
627 # Close and reopen the connection. | |
628 db close | |
629 sqlite3 db test.db | |
630 | |
631 # Test we are still in incremental vacuum mode. | |
632 execsql { PRAGMA auto_vacuum; } | |
633 } {2} | |
634 do_test incrvacuum-11.6 { | |
635 execsql { | |
636 PRAGMA auto_vacuum = 'full'; | |
637 PRAGMA auto_vacuum; | |
638 } | |
639 } {1} | |
640 do_test incrvacuum-11.7 { | |
641 # Close and reopen the connection. | |
642 db close | |
643 sqlite3 db test.db | |
644 | |
645 # Test we are still in "full" auto-vacuum mode. | |
646 execsql { PRAGMA auto_vacuum; } | |
647 } {1} | |
648 | |
649 #---------------------------------------------------------------------- | |
650 # Special case: What happens if the database is locked when a "PRAGMA | |
651 # auto_vacuum = XXX" statement is executed. | |
652 # | |
653 db close | |
654 forcedelete test.db test.db-journal | |
655 sqlite3 db test.db | |
656 | |
657 do_test incrvacuum-12.1 { | |
658 execsql { | |
659 PRAGMA auto_vacuum = 1; | |
660 } | |
661 expr {[file size test.db]>0} | |
662 } {1} | |
663 | |
664 # Try to change the auto-vacuum from "full" to "incremental" while the | |
665 # database is locked. Nothing should change. | |
666 # | |
667 do_test incrvacuum-12.2 { | |
668 sqlite3 db2 test.db | |
669 execsql { BEGIN EXCLUSIVE; } db2 | |
670 catchsql { PRAGMA auto_vacuum = 2; } | |
671 } {1 {database is locked}} | |
672 | |
673 do_test incrvacuum-12.3 { | |
674 execsql { ROLLBACK; } db2 | |
675 execsql { PRAGMA auto_vacuum } | |
676 } {2} ;# Still 2 because PRAGMA auto_vacuum setting held in case of vacuum | |
677 do_test incrvacuum-12.4 { | |
678 db close | |
679 sqlite3 db test.db | |
680 execsql { PRAGMA auto_vacuum } | |
681 } {1} ;# Revert to 1 because the database file did not change | |
682 | |
683 do_test incrvacuum-12.5 { | |
684 execsql { SELECT * FROM sqlite_master } | |
685 execsql { PRAGMA auto_vacuum } | |
686 } {1} | |
687 | |
688 #---------------------------------------------------------------------- | |
689 # Special case #2: What if one process prepares a "PRAGMA auto_vacuum = XXX" | |
690 # statement when the database is empty, but doesn't execute it until | |
691 # after some other process has created the database. | |
692 # | |
693 db2 close | |
694 db close | |
695 forcedelete test.db test.db-journal | |
696 sqlite3 db test.db ; set ::DB [sqlite3_connection_pointer db] | |
697 sqlite3 db2 test.db | |
698 | |
699 do_test incrvacuum-13.1 { | |
700 # File size is sometimes 1 instead of 0 due to the hack we put in | |
701 # to work around ticket #3260. Search for comments on #3260 in | |
702 # os_unix.c. | |
703 expr {[file size test.db]>1} | |
704 } {0} | |
705 do_test incrvacuum-13.2 { | |
706 set ::STMT [sqlite3_prepare $::DB {PRAGMA auto_vacuum = 2} -1 DUMMY] | |
707 execsql { | |
708 PRAGMA auto_vacuum = none; | |
709 PRAGMA default_cache_size = 1024; | |
710 PRAGMA auto_vacuum; | |
711 } db2 | |
712 } {0} | |
713 do_test incrvacuum-13.3 { | |
714 expr {[file size test.db]>0} | |
715 } {1} | |
716 do_test incrvacuum-13.4 { | |
717 set rc [sqlite3_step $::STMT] | |
718 list $rc [sqlite3_finalize $::STMT] | |
719 } {SQLITE_DONE SQLITE_OK} | |
720 do_test incrvacuum-13.5 { | |
721 execsql { | |
722 PRAGMA auto_vacuum; | |
723 } | |
724 } {0} | |
725 | |
726 | |
727 # Verify that the incremental_vacuum pragma fails gracefully if it | |
728 # is used against an invalid database file. | |
729 # | |
730 if {[permutation] == ""} { | |
731 do_test incrvacuum-14.1 { | |
732 set out [open invalid.db w] | |
733 puts $out "This is not an SQLite database file" | |
734 close $out | |
735 sqlite3 db3 invalid.db | |
736 catchsql { | |
737 PRAGMA incremental_vacuum(10); | |
738 } db3 | |
739 } {1 {file is encrypted or is not a database}} | |
740 db3 close | |
741 } | |
742 | |
743 do_test incrvacuum-15.1 { | |
744 db close | |
745 db2 close | |
746 forcedelete test.db | |
747 sqlite3 db test.db | |
748 | |
749 set str [string repeat "abcdefghij" 500] | |
750 | |
751 execsql { | |
752 PRAGMA cache_size = 10; | |
753 PRAGMA auto_vacuum = incremental; | |
754 CREATE TABLE t1(x, y); | |
755 INSERT INTO t1 VALUES('a', $str); | |
756 INSERT INTO t1 VALUES('b', $str); | |
757 INSERT INTO t1 VALUES('c', $str); | |
758 INSERT INTO t1 VALUES('d', $str); | |
759 INSERT INTO t1 VALUES('e', $str); | |
760 INSERT INTO t1 VALUES('f', $str); | |
761 INSERT INTO t1 VALUES('g', $str); | |
762 INSERT INTO t1 VALUES('h', $str); | |
763 INSERT INTO t1 VALUES('i', $str); | |
764 INSERT INTO t1 VALUES('j', $str); | |
765 INSERT INTO t1 VALUES('j', $str); | |
766 | |
767 CREATE TABLE t2(x PRIMARY KEY, y); | |
768 INSERT INTO t2 VALUES('a', $str); | |
769 INSERT INTO t2 VALUES('b', $str); | |
770 INSERT INTO t2 VALUES('c', $str); | |
771 INSERT INTO t2 VALUES('d', $str); | |
772 | |
773 BEGIN; | |
774 DELETE FROM t2; | |
775 PRAGMA incremental_vacuum; | |
776 } | |
777 | |
778 catchsql {INSERT INTO t2 SELECT * FROM t1} | |
779 | |
780 execsql { | |
781 COMMIT; | |
782 PRAGMA integrity_check; | |
783 } | |
784 } {ok} | |
785 | |
786 finish_test | |
OLD | NEW |