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