Annotation of embedaddon/sqlite3/test/autovacuum.test, revision 1.1
1.1 ! misho 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
! 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 {indexed columns are not unique}}
! 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
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>