OLD | NEW |
| (Empty) |
1 # 2001 September 15 | |
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 SELECT statement. | |
13 # | |
14 # $Id: autovacuum.test,v 1.29 2009/04/06 17:50:03 danielk1977 Exp $ | |
15 | |
16 set testdir [file dirname $argv0] | |
17 source $testdir/tester.tcl | |
18 | |
19 # If this build of the library does not support auto-vacuum, omit this | |
20 # whole file. | |
21 ifcapable {!autovacuum || !pragma} { | |
22 finish_test | |
23 return | |
24 } | |
25 | |
26 # Return a string $len characters long. The returned string is $char repeated | |
27 # over and over. For example, [make_str abc 8] returns "abcabcab". | |
28 proc make_str {char len} { | |
29 set str [string repeat $char. $len] | |
30 return [string range $str 0 [expr $len-1]] | |
31 } | |
32 | |
33 # Return the number of pages in the file test.db by looking at the file system. | |
34 proc file_pages {} { | |
35 return [expr [file size test.db] / 1024] | |
36 } | |
37 | |
38 #------------------------------------------------------------------------- | |
39 # Test cases autovacuum-1.* work as follows: | |
40 # | |
41 # 1. A table with a single indexed field is created. | |
42 # 2. Approximately 20 rows are inserted into the table. Each row is long | |
43 # enough such that it uses at least 2 overflow pages for both the table | |
44 # and index entry. | |
45 # 3. The rows are deleted in a psuedo-random order. Sometimes only one row | |
46 # is deleted per transaction, sometimes more than one. | |
47 # 4. After each transaction the table data is checked to ensure it is correct | |
48 # and a "PRAGMA integrity_check" is executed. | |
49 # 5. Once all the rows are deleted the file is checked to make sure it | |
50 # consists of exactly 4 pages. | |
51 # | |
52 # Steps 2-5 are repeated for a few different psuedo-random delete patterns | |
53 # (defined by the $delete_orders list). | |
54 set delete_orders [list] | |
55 lappend delete_orders {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20} | |
56 lappend delete_orders {20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1} | |
57 lappend delete_orders {8 18 2 4 14 11 13 3 10 7 9 5 12 17 19 15 20 6 16 1} | |
58 lappend delete_orders {10 3 11 17 19 20 7 4 13 6 1 14 16 12 9 18 8 15 5 2} | |
59 lappend delete_orders {{1 2 3 4 5 6 7 8 9 10} {11 12 13 14 15 16 17 18 19 20}} | |
60 lappend delete_orders {{19 8 17 15} {16 11 9 14} {18 5 3 1} {13 20 7 2} {6 12}} | |
61 | |
62 # The length of each table entry. | |
63 # set ENTRY_LEN 3500 | |
64 set ENTRY_LEN 3500 | |
65 | |
66 do_test autovacuum-1.1 { | |
67 execsql { | |
68 PRAGMA auto_vacuum = 1; | |
69 CREATE TABLE av1(a); | |
70 CREATE INDEX av1_idx ON av1(a); | |
71 } | |
72 } {} | |
73 | |
74 set tn 0 | |
75 foreach delete_order $delete_orders { | |
76 incr tn | |
77 | |
78 # Set up the table. | |
79 set ::tbl_data [list] | |
80 foreach i [lsort -integer [eval concat $delete_order]] { | |
81 execsql "INSERT INTO av1 (oid, a) VALUES($i, '[make_str $i $ENTRY_LEN]')" | |
82 lappend ::tbl_data [make_str $i $ENTRY_LEN] | |
83 } | |
84 | |
85 # Make sure the integrity check passes with the initial data. | |
86 ifcapable {integrityck} { | |
87 do_test autovacuum-1.$tn.1 { | |
88 execsql { | |
89 pragma integrity_check | |
90 } | |
91 } {ok} | |
92 } | |
93 | |
94 foreach delete $delete_order { | |
95 # Delete one set of rows from the table. | |
96 do_test autovacuum-1.$tn.($delete).1 { | |
97 execsql " | |
98 DELETE FROM av1 WHERE oid = [join $delete " OR oid = "] | |
99 " | |
100 } {} | |
101 | |
102 # Do the integrity check. | |
103 ifcapable {integrityck} { | |
104 do_test autovacuum-1.$tn.($delete).2 { | |
105 execsql { | |
106 pragma integrity_check | |
107 } | |
108 } {ok} | |
109 } | |
110 # Ensure the data remaining in the table is what was expected. | |
111 foreach d $delete { | |
112 set idx [lsearch $::tbl_data [make_str $d $ENTRY_LEN]] | |
113 set ::tbl_data [lreplace $::tbl_data $idx $idx] | |
114 } | |
115 do_test autovacuum-1.$tn.($delete).3 { | |
116 execsql { | |
117 select a from av1 order by rowid | |
118 } | |
119 } $::tbl_data | |
120 } | |
121 | |
122 # All rows have been deleted. Ensure the file has shrunk to 4 pages. | |
123 do_test autovacuum-1.$tn.3 { | |
124 file_pages | |
125 } {4} | |
126 } | |
127 | |
128 #--------------------------------------------------------------------------- | |
129 # Tests cases autovacuum-2.* test that root pages are allocated | |
130 # and deallocated correctly at the start of the file. Operation is roughly as | |
131 # follows: | |
132 # | |
133 # autovacuum-2.1.*: Drop the tables that currently exist in the database. | |
134 # autovacuum-2.2.*: Create some tables. Ensure that data pages can be | |
135 # moved correctly to make space for new root-pages. | |
136 # autovacuum-2.3.*: Drop one of the tables just created (not the last one), | |
137 # and check that one of the other tables is moved to | |
138 # the free root-page location. | |
139 # autovacuum-2.4.*: Check that a table can be created correctly when the | |
140 # root-page it requires is on the free-list. | |
141 # autovacuum-2.5.*: Check that a table with indices can be dropped. This | |
142 # is slightly tricky because dropping one of the | |
143 # indices/table btrees could move the root-page of another. | |
144 # The code-generation layer of SQLite overcomes this problem | |
145 # by dropping the btrees in descending order of root-pages. | |
146 # This test ensures that this actually happens. | |
147 # | |
148 do_test autovacuum-2.1.1 { | |
149 execsql { | |
150 DROP TABLE av1; | |
151 } | |
152 } {} | |
153 do_test autovacuum-2.1.2 { | |
154 file_pages | |
155 } {1} | |
156 | |
157 # Create a table and put some data in it. | |
158 do_test autovacuum-2.2.1 { | |
159 execsql { | |
160 CREATE TABLE av1(x); | |
161 SELECT rootpage FROM sqlite_master ORDER BY rootpage; | |
162 } | |
163 } {3} | |
164 do_test autovacuum-2.2.2 { | |
165 execsql " | |
166 INSERT INTO av1 VALUES('[make_str abc 3000]'); | |
167 INSERT INTO av1 VALUES('[make_str def 3000]'); | |
168 INSERT INTO av1 VALUES('[make_str ghi 3000]'); | |
169 INSERT INTO av1 VALUES('[make_str jkl 3000]'); | |
170 " | |
171 set ::av1_data [db eval {select * from av1}] | |
172 file_pages | |
173 } {15} | |
174 | |
175 # Create another table. Check it is located immediately after the first. | |
176 # This test case moves the second page in an over-flow chain. | |
177 do_test autovacuum-2.2.3 { | |
178 execsql { | |
179 CREATE TABLE av2(x); | |
180 SELECT rootpage FROM sqlite_master ORDER BY rootpage; | |
181 } | |
182 } {3 4} | |
183 do_test autovacuum-2.2.4 { | |
184 file_pages | |
185 } {16} | |
186 | |
187 # Create another table. Check it is located immediately after the second. | |
188 # This test case moves the first page in an over-flow chain. | |
189 do_test autovacuum-2.2.5 { | |
190 execsql { | |
191 CREATE TABLE av3(x); | |
192 SELECT rootpage FROM sqlite_master ORDER BY rootpage; | |
193 } | |
194 } {3 4 5} | |
195 do_test autovacuum-2.2.6 { | |
196 file_pages | |
197 } {17} | |
198 | |
199 # Create another table. Check it is located immediately after the second. | |
200 # This test case moves a btree leaf page. | |
201 do_test autovacuum-2.2.7 { | |
202 execsql { | |
203 CREATE TABLE av4(x); | |
204 SELECT rootpage FROM sqlite_master ORDER BY rootpage; | |
205 } | |
206 } {3 4 5 6} | |
207 do_test autovacuum-2.2.8 { | |
208 file_pages | |
209 } {18} | |
210 do_test autovacuum-2.2.9 { | |
211 execsql { | |
212 select * from av1 | |
213 } | |
214 } $av1_data | |
215 | |
216 do_test autovacuum-2.3.1 { | |
217 execsql { | |
218 INSERT INTO av2 SELECT 'av1' || x FROM av1; | |
219 INSERT INTO av3 SELECT 'av2' || x FROM av1; | |
220 INSERT INTO av4 SELECT 'av3' || x FROM av1; | |
221 } | |
222 set ::av2_data [execsql {select x from av2}] | |
223 set ::av3_data [execsql {select x from av3}] | |
224 set ::av4_data [execsql {select x from av4}] | |
225 file_pages | |
226 } {54} | |
227 do_test autovacuum-2.3.2 { | |
228 execsql { | |
229 DROP TABLE av2; | |
230 SELECT rootpage FROM sqlite_master ORDER BY rootpage; | |
231 } | |
232 } {3 4 5} | |
233 do_test autovacuum-2.3.3 { | |
234 file_pages | |
235 } {41} | |
236 do_test autovacuum-2.3.4 { | |
237 execsql { | |
238 SELECT x FROM av3; | |
239 } | |
240 } $::av3_data | |
241 do_test autovacuum-2.3.5 { | |
242 execsql { | |
243 SELECT x FROM av4; | |
244 } | |
245 } $::av4_data | |
246 | |
247 # Drop all the tables in the file. This puts all pages except the first 2 | |
248 # (the sqlite_master root-page and the first pointer map page) on the | |
249 # free-list. | |
250 do_test autovacuum-2.4.1 { | |
251 execsql { | |
252 DROP TABLE av1; | |
253 DROP TABLE av3; | |
254 BEGIN; | |
255 DROP TABLE av4; | |
256 } | |
257 file_pages | |
258 } {15} | |
259 do_test autovacuum-2.4.2 { | |
260 for {set i 3} {$i<=10} {incr i} { | |
261 execsql "CREATE TABLE av$i (x)" | |
262 } | |
263 file_pages | |
264 } {15} | |
265 do_test autovacuum-2.4.3 { | |
266 execsql { | |
267 SELECT rootpage FROM sqlite_master ORDER by rootpage | |
268 } | |
269 } {3 4 5 6 7 8 9 10} | |
270 | |
271 # Right now there are 5 free pages in the database. Consume and then free | |
272 # a 520 pages. Then create 520 tables. This ensures that at least some of the | |
273 # desired root-pages reside on the second free-list trunk page, and that the | |
274 # trunk itself is required at some point. | |
275 do_test autovacuum-2.4.4 { | |
276 execsql " | |
277 INSERT INTO av3 VALUES ('[make_str abcde [expr 1020*520 + 500]]'); | |
278 DELETE FROM av3; | |
279 " | |
280 } {} | |
281 set root_page_list [list] | |
282 set pending_byte_page [expr ($::sqlite_pending_byte / 1024) + 1] | |
283 for {set i 3} {$i<=532} {incr i} { | |
284 # 207 and 412 are pointer-map pages. | |
285 if { $i!=207 && $i!=412 && $i != $pending_byte_page} { | |
286 lappend root_page_list $i | |
287 } | |
288 } | |
289 if {$i >= $pending_byte_page} { | |
290 lappend root_page_list $i | |
291 } | |
292 do_test autovacuum-2.4.5 { | |
293 for {set i 11} {$i<=530} {incr i} { | |
294 execsql "CREATE TABLE av$i (x)" | |
295 } | |
296 execsql { | |
297 SELECT rootpage FROM sqlite_master ORDER by rootpage | |
298 } | |
299 } $root_page_list | |
300 | |
301 # Just for fun, delete all those tables and see if the database is 1 page. | |
302 do_test autovacuum-2.4.6 { | |
303 execsql COMMIT; | |
304 file_pages | |
305 } [expr 561 + (($i >= $pending_byte_page)?1:0)] | |
306 integrity_check autovacuum-2.4.6 | |
307 do_test autovacuum-2.4.7 { | |
308 execsql BEGIN | |
309 for {set i 3} {$i<=530} {incr i} { | |
310 execsql "DROP TABLE av$i" | |
311 } | |
312 execsql COMMIT | |
313 file_pages | |
314 } 1 | |
315 | |
316 # Create some tables with indices to drop. | |
317 do_test autovacuum-2.5.1 { | |
318 execsql { | |
319 CREATE TABLE av1(a PRIMARY KEY, b, c); | |
320 INSERT INTO av1 VALUES('av1 a', 'av1 b', 'av1 c'); | |
321 | |
322 CREATE TABLE av2(a PRIMARY KEY, b, c); | |
323 CREATE INDEX av2_i1 ON av2(b); | |
324 CREATE INDEX av2_i2 ON av2(c); | |
325 INSERT INTO av2 VALUES('av2 a', 'av2 b', 'av2 c'); | |
326 | |
327 CREATE TABLE av3(a PRIMARY KEY, b, c); | |
328 CREATE INDEX av3_i1 ON av3(b); | |
329 INSERT INTO av3 VALUES('av3 a', 'av3 b', 'av3 c'); | |
330 | |
331 CREATE TABLE av4(a, b, c); | |
332 CREATE INDEX av4_i1 ON av4(a); | |
333 CREATE INDEX av4_i2 ON av4(b); | |
334 CREATE INDEX av4_i3 ON av4(c); | |
335 CREATE INDEX av4_i4 ON av4(a, b, c); | |
336 INSERT INTO av4 VALUES('av4 a', 'av4 b', 'av4 c'); | |
337 } | |
338 } {} | |
339 | |
340 do_test autovacuum-2.5.2 { | |
341 execsql { | |
342 SELECT name, rootpage FROM sqlite_master; | |
343 } | |
344 } [list av1 3 sqlite_autoindex_av1_1 4 \ | |
345 av2 5 sqlite_autoindex_av2_1 6 av2_i1 7 av2_i2 8 \ | |
346 av3 9 sqlite_autoindex_av3_1 10 av3_i1 11 \ | |
347 av4 12 av4_i1 13 av4_i2 14 av4_i3 15 av4_i4 16 \ | |
348 ] | |
349 | |
350 # The following 4 tests are SELECT queries that use the indices created. | |
351 # If the root-pages in the internal schema are not updated correctly when | |
352 # a table or indice is moved, these queries will fail. They are repeated | |
353 # after each table is dropped (i.e. as test cases 2.5.*.[1..4]). | |
354 do_test autovacuum-2.5.2.1 { | |
355 execsql { | |
356 SELECT * FROM av1 WHERE a = 'av1 a'; | |
357 } | |
358 } {{av1 a} {av1 b} {av1 c}} | |
359 do_test autovacuum-2.5.2.2 { | |
360 execsql { | |
361 SELECT * FROM av2 WHERE a = 'av2 a' AND b = 'av2 b' AND c = 'av2 c' | |
362 } | |
363 } {{av2 a} {av2 b} {av2 c}} | |
364 do_test autovacuum-2.5.2.3 { | |
365 execsql { | |
366 SELECT * FROM av3 WHERE a = 'av3 a' AND b = 'av3 b'; | |
367 } | |
368 } {{av3 a} {av3 b} {av3 c}} | |
369 do_test autovacuum-2.5.2.4 { | |
370 execsql { | |
371 SELECT * FROM av4 WHERE a = 'av4 a' AND b = 'av4 b' AND c = 'av4 c'; | |
372 } | |
373 } {{av4 a} {av4 b} {av4 c}} | |
374 | |
375 # Drop table av3. Indices av4_i2, av4_i3 and av4_i4 are moved to fill the two | |
376 # root pages vacated. The operation proceeds as: | |
377 # Step 1: Delete av3_i1 (root-page 11). Move root-page of av4_i4 to page 11. | |
378 # Step 2: Delete av3 (root-page 10). Move root-page of av4_i3 to page 10. | |
379 # Step 3: Delete sqlite_autoindex_av1_3 (root-page 9). Move av4_i2 to page 9. | |
380 do_test autovacuum-2.5.3 { | |
381 execsql { | |
382 DROP TABLE av3; | |
383 SELECT name, rootpage FROM sqlite_master; | |
384 } | |
385 } [list av1 3 sqlite_autoindex_av1_1 4 \ | |
386 av2 5 sqlite_autoindex_av2_1 6 av2_i1 7 av2_i2 8 \ | |
387 av4 12 av4_i1 13 av4_i2 9 av4_i3 10 av4_i4 11 \ | |
388 ] | |
389 do_test autovacuum-2.5.3.1 { | |
390 execsql { | |
391 SELECT * FROM av1 WHERE a = 'av1 a'; | |
392 } | |
393 } {{av1 a} {av1 b} {av1 c}} | |
394 do_test autovacuum-2.5.3.2 { | |
395 execsql { | |
396 SELECT * FROM av2 WHERE a = 'av2 a' AND b = 'av2 b' AND c = 'av2 c' | |
397 } | |
398 } {{av2 a} {av2 b} {av2 c}} | |
399 do_test autovacuum-2.5.3.3 { | |
400 execsql { | |
401 SELECT * FROM av4 WHERE a = 'av4 a' AND b = 'av4 b' AND c = 'av4 c'; | |
402 } | |
403 } {{av4 a} {av4 b} {av4 c}} | |
404 | |
405 # Drop table av1: | |
406 # Step 1: Delete av1 (root page 4). Root-page of av4_i1 fills the gap. | |
407 # Step 2: Delete sqlite_autoindex_av1_1 (root page 3). Move av4 to the gap. | |
408 do_test autovacuum-2.5.4 { | |
409 execsql { | |
410 DROP TABLE av1; | |
411 SELECT name, rootpage FROM sqlite_master; | |
412 } | |
413 } [list av2 5 sqlite_autoindex_av2_1 6 av2_i1 7 av2_i2 8 \ | |
414 av4 3 av4_i1 4 av4_i2 9 av4_i3 10 av4_i4 11 \ | |
415 ] | |
416 do_test autovacuum-2.5.4.2 { | |
417 execsql { | |
418 SELECT * FROM av2 WHERE a = 'av2 a' AND b = 'av2 b' AND c = 'av2 c' | |
419 } | |
420 } {{av2 a} {av2 b} {av2 c}} | |
421 do_test autovacuum-2.5.4.4 { | |
422 execsql { | |
423 SELECT * FROM av4 WHERE a = 'av4 a' AND b = 'av4 b' AND c = 'av4 c'; | |
424 } | |
425 } {{av4 a} {av4 b} {av4 c}} | |
426 | |
427 # Drop table av4: | |
428 # Step 1: Delete av4_i4. | |
429 # Step 2: Delete av4_i3. | |
430 # Step 3: Delete av4_i2. | |
431 # Step 4: Delete av4_i1. av2_i2 replaces it. | |
432 # Step 5: Delete av4. av2_i1 replaces it. | |
433 do_test autovacuum-2.5.5 { | |
434 execsql { | |
435 DROP TABLE av4; | |
436 SELECT name, rootpage FROM sqlite_master; | |
437 } | |
438 } [list av2 5 sqlite_autoindex_av2_1 6 av2_i1 3 av2_i2 4] | |
439 do_test autovacuum-2.5.5.2 { | |
440 execsql { | |
441 SELECT * FROM av2 WHERE a = 'av2 a' AND b = 'av2 b' AND c = 'av2 c' | |
442 } | |
443 } {{av2 a} {av2 b} {av2 c}} | |
444 | |
445 #-------------------------------------------------------------------------- | |
446 # Test cases autovacuum-3.* test the operation of the "PRAGMA auto_vacuum" | |
447 # command. | |
448 # | |
449 do_test autovacuum-3.1 { | |
450 execsql { | |
451 PRAGMA auto_vacuum; | |
452 } | |
453 } {1} | |
454 do_test autovacuum-3.2 { | |
455 db close | |
456 sqlite3 db test.db | |
457 execsql { | |
458 PRAGMA auto_vacuum; | |
459 } | |
460 } {1} | |
461 do_test autovacuum-3.3 { | |
462 execsql { | |
463 PRAGMA auto_vacuum = 0; | |
464 PRAGMA auto_vacuum; | |
465 } | |
466 } {1} | |
467 | |
468 do_test autovacuum-3.4 { | |
469 db close | |
470 forcedelete test.db | |
471 sqlite3 db test.db | |
472 execsql { | |
473 PRAGMA auto_vacuum; | |
474 } | |
475 } $AUTOVACUUM | |
476 do_test autovacuum-3.5 { | |
477 execsql { | |
478 CREATE TABLE av1(x); | |
479 PRAGMA auto_vacuum; | |
480 } | |
481 } $AUTOVACUUM | |
482 do_test autovacuum-3.6 { | |
483 execsql { | |
484 PRAGMA auto_vacuum = 1; | |
485 PRAGMA auto_vacuum; | |
486 } | |
487 } [expr $AUTOVACUUM ? 1 : 0] | |
488 do_test autovacuum-3.7 { | |
489 execsql { | |
490 DROP TABLE av1; | |
491 } | |
492 file_pages | |
493 } [expr $AUTOVACUUM?1:2] | |
494 | |
495 | |
496 #----------------------------------------------------------------------- | |
497 # Test that if a statement transaction around a CREATE INDEX statement is | |
498 # rolled back no corruption occurs. | |
499 # | |
500 do_test autovacuum-4.0 { | |
501 # The last round of tests may have left the db in non-autovacuum mode. | |
502 # Reset everything just in case. | |
503 # | |
504 db close | |
505 forcedelete test.db test.db-journal | |
506 sqlite3 db test.db | |
507 execsql { | |
508 PRAGMA auto_vacuum = 1; | |
509 PRAGMA auto_vacuum; | |
510 } | |
511 } {1} | |
512 do_test autovacuum-4.1 { | |
513 execsql { | |
514 CREATE TABLE av1(a, b); | |
515 BEGIN; | |
516 } | |
517 for {set i 0} {$i<100} {incr i} { | |
518 execsql "INSERT INTO av1 VALUES($i, '[string repeat X 200]');" | |
519 } | |
520 execsql "INSERT INTO av1 VALUES(99, '[string repeat X 200]');" | |
521 execsql { | |
522 SELECT sum(a) FROM av1; | |
523 } | |
524 } {5049} | |
525 do_test autovacuum-4.2 { | |
526 catchsql { | |
527 CREATE UNIQUE INDEX av1_i ON av1(a); | |
528 } | |
529 } {1 {UNIQUE constraint failed: av1.a}} | |
530 do_test autovacuum-4.3 { | |
531 execsql { | |
532 SELECT sum(a) FROM av1; | |
533 } | |
534 } {5049} | |
535 do_test autovacuum-4.4 { | |
536 execsql { | |
537 COMMIT; | |
538 } | |
539 } {} | |
540 | |
541 ifcapable integrityck { | |
542 | |
543 # Ticket #1727 | |
544 do_test autovacuum-5.1 { | |
545 db close | |
546 sqlite3 db :memory: | |
547 db eval { | |
548 PRAGMA auto_vacuum=1; | |
549 CREATE TABLE t1(a); | |
550 CREATE TABLE t2(a); | |
551 DROP TABLE t1; | |
552 PRAGMA integrity_check; | |
553 } | |
554 } ok | |
555 | |
556 } | |
557 | |
558 # Ticket #1728. | |
559 # | |
560 # In autovacuum mode, when tables or indices are deleted, the rootpage | |
561 # values in the symbol table have to be updated. There was a bug in this | |
562 # logic so that if an index/table was moved twice, the second move might | |
563 # not occur. This would leave the internal symbol table in an inconsistent | |
564 # state causing subsequent statements to fail. | |
565 # | |
566 # The problem is difficult to reproduce. The sequence of statements in | |
567 # the following test are carefully designed make it occur and thus to | |
568 # verify that this very obscure bug has been resolved. | |
569 # | |
570 ifcapable integrityck&&memorydb { | |
571 | |
572 do_test autovacuum-6.1 { | |
573 db close | |
574 sqlite3 db :memory: | |
575 db eval { | |
576 PRAGMA auto_vacuum=1; | |
577 CREATE TABLE t1(a, b); | |
578 CREATE INDEX i1 ON t1(a); | |
579 CREATE TABLE t2(a); | |
580 CREATE INDEX i2 ON t2(a); | |
581 CREATE TABLE t3(a); | |
582 CREATE INDEX i3 ON t2(a); | |
583 CREATE INDEX x ON t1(b); | |
584 DROP TABLE t3; | |
585 PRAGMA integrity_check; | |
586 DROP TABLE t2; | |
587 PRAGMA integrity_check; | |
588 DROP TABLE t1; | |
589 PRAGMA integrity_check; | |
590 } | |
591 } {ok ok ok} | |
592 | |
593 } | |
594 | |
595 #--------------------------------------------------------------------- | |
596 # Test cases autovacuum-7.X test the case where a page must be moved | |
597 # and the destination location collides with at least one other | |
598 # entry in the page hash-table (internal to the pager.c module. | |
599 # | |
600 do_test autovacuum-7.1 { | |
601 db close | |
602 forcedelete test.db | |
603 forcedelete test.db-journal | |
604 sqlite3 db test.db | |
605 | |
606 execsql { | |
607 PRAGMA auto_vacuum=1; | |
608 CREATE TABLE t1(a, b, PRIMARY KEY(a, b)); | |
609 INSERT INTO t1 VALUES(randstr(400,400),randstr(400,400)); | |
610 INSERT INTO t1 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 2 | |
611 INSERT INTO t1 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 4 | |
612 INSERT INTO t1 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 8 | |
613 INSERT INTO t1 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 16 | |
614 INSERT INTO t1 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 32 | |
615 } | |
616 | |
617 expr {[file size test.db] / 1024} | |
618 } {73} | |
619 | |
620 do_test autovacuum-7.2 { | |
621 execsql { | |
622 CREATE TABLE t2(a, b, PRIMARY KEY(a, b)); | |
623 INSERT INTO t2 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 2 | |
624 CREATE TABLE t3(a, b, PRIMARY KEY(a, b)); | |
625 INSERT INTO t3 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 2 | |
626 CREATE TABLE t4(a, b, PRIMARY KEY(a, b)); | |
627 INSERT INTO t4 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 2 | |
628 CREATE TABLE t5(a, b, PRIMARY KEY(a, b)); | |
629 INSERT INTO t5 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 2 | |
630 } | |
631 expr {[file size test.db] / 1024} | |
632 } {354} | |
633 | |
634 do_test autovacuum-7.3 { | |
635 db close | |
636 sqlite3 db test.db | |
637 execsql { | |
638 BEGIN; | |
639 DELETE FROM t4; | |
640 COMMIT; | |
641 SELECT count(*) FROM t1; | |
642 } | |
643 expr {[file size test.db] / 1024} | |
644 } {286} | |
645 | |
646 #------------------------------------------------------------------------ | |
647 # Additional tests. | |
648 # | |
649 # Try to determine the autovacuum setting for a database that is locked. | |
650 # | |
651 do_test autovacuum-8.1 { | |
652 db close | |
653 sqlite3 db test.db | |
654 sqlite3 db2 test.db | |
655 db eval {PRAGMA auto_vacuum} | |
656 } {1} | |
657 if {[permutation] == ""} { | |
658 do_test autovacuum-8.2 { | |
659 db eval {BEGIN EXCLUSIVE} | |
660 catchsql {PRAGMA auto_vacuum} db2 | |
661 } {1 {database is locked}} | |
662 catch {db2 close} | |
663 catch {db eval {COMMIT}} | |
664 } | |
665 | |
666 do_test autovacuum-9.1 { | |
667 execsql { | |
668 DROP TABLE t1; | |
669 DROP TABLE t2; | |
670 DROP TABLE t3; | |
671 DROP TABLE t4; | |
672 DROP TABLE t5; | |
673 PRAGMA page_count; | |
674 } | |
675 } {1} | |
676 do_test autovacuum-9.2 { | |
677 file size test.db | |
678 } 1024 | |
679 do_test autovacuum-9.3 { | |
680 execsql { | |
681 CREATE TABLE t1(a INTEGER PRIMARY KEY, b); | |
682 INSERT INTO t1 VALUES(NULL, randstr(50,50)); | |
683 } | |
684 for {set ii 0} {$ii < 10} {incr ii} { | |
685 db eval { INSERT INTO t1 SELECT NULL, randstr(50,50) FROM t1 } | |
686 } | |
687 file size test.db | |
688 } $::sqlite_pending_byte | |
689 do_test autovacuum-9.4 { | |
690 execsql { INSERT INTO t1 SELECT NULL, randstr(50,50) FROM t1 } | |
691 } {} | |
692 do_test autovacuum-9.5 { | |
693 execsql { DELETE FROM t1 WHERE rowid > (SELECT max(a)/2 FROM t1) } | |
694 file size test.db | |
695 } $::sqlite_pending_byte | |
696 | |
697 | |
698 finish_test | |
OLD | NEW |