File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sqlite3 / test / autovacuum.test
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:04:16 2012 UTC (12 years, 10 months ago) by misho
Branches: sqlite3, MAIN
CVS tags: v3_7_10, HEAD
sqlite3

    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.1.1.1 2012/02/21 17:04:16 misho 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>