Annotation of embedaddon/sqlite3/test/autovacuum.test, revision 1.1.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>