github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/autovacuum.test (about)

     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  # all 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  
   284  # unusable_pages
   285  # These are either the pending_byte page or the pointer map pages
   286  #
   287  unset -nocomplain unusable_page
   288  if {[sqlite3 -has-codec]} {
   289    array set unusable_page {205 1 408 1}
   290  } else {
   291    array set unusable_page {207 1 412 1}
   292  }
   293  set unusable_page($pending_byte_page) 1
   294  
   295  for {set i 3} {$i<=532} {incr i} {
   296    if {![info exists unusable_page($i)]} {
   297      lappend root_page_list $i
   298    }
   299  }
   300  if {$i >= $pending_byte_page} {
   301    lappend root_page_list $i
   302  }
   303  do_test autovacuum-2.4.5 {
   304    for {set i 11} {$i<=530} {incr i} {
   305      execsql "CREATE TABLE av$i (x)"
   306    }
   307    execsql {
   308      SELECT rootpage FROM sqlite_master ORDER by rootpage
   309    }
   310  } $root_page_list
   311  
   312  # Just for fun, delete all those tables and see if the database is 1 page.
   313  do_test autovacuum-2.4.6 {
   314    execsql COMMIT;
   315    file_pages
   316  } [expr 561 + (($i >= $pending_byte_page)?1:0)]
   317  integrity_check autovacuum-2.4.6
   318  do_test autovacuum-2.4.7 {
   319    execsql BEGIN
   320    for {set i 3} {$i<=530} {incr i} {
   321      execsql "DROP TABLE av$i"
   322    }
   323    execsql COMMIT
   324    file_pages
   325  } 1
   326  
   327  # Create some tables with indices to drop.
   328  do_test autovacuum-2.5.1 {
   329    execsql {
   330      CREATE TABLE av1(a PRIMARY KEY, b, c);
   331      INSERT INTO av1 VALUES('av1 a', 'av1 b', 'av1 c');
   332  
   333      CREATE TABLE av2(a PRIMARY KEY, b, c);
   334      CREATE INDEX av2_i1 ON av2(b);
   335      CREATE INDEX av2_i2 ON av2(c);
   336      INSERT INTO av2 VALUES('av2 a', 'av2 b', 'av2 c');
   337  
   338      CREATE TABLE av3(a PRIMARY KEY, b, c);
   339      CREATE INDEX av3_i1 ON av3(b);
   340      INSERT INTO av3 VALUES('av3 a', 'av3 b', 'av3 c');
   341  
   342      CREATE TABLE av4(a, b, c);
   343      CREATE INDEX av4_i1 ON av4(a);
   344      CREATE INDEX av4_i2 ON av4(b);
   345      CREATE INDEX av4_i3 ON av4(c);
   346      CREATE INDEX av4_i4 ON av4(a, b, c);
   347      INSERT INTO av4 VALUES('av4 a', 'av4 b', 'av4 c');
   348    }
   349  } {}
   350  
   351  do_test autovacuum-2.5.2 {
   352    execsql {
   353      SELECT name, rootpage FROM sqlite_master;
   354    }
   355  } [list av1 3  sqlite_autoindex_av1_1 4 \
   356          av2 5  sqlite_autoindex_av2_1 6 av2_i1 7 av2_i2 8 \
   357          av3 9 sqlite_autoindex_av3_1 10 av3_i1 11 \
   358          av4 12 av4_i1 13 av4_i2 14 av4_i3 15 av4_i4 16 \
   359  ]
   360  
   361  # The following 4 tests are SELECT queries that use the indices created.
   362  # If the root-pages in the internal schema are not updated correctly when
   363  # a table or indice is moved, these queries will fail. They are repeated
   364  # after each table is dropped (i.e. as test cases 2.5.*.[1..4]).
   365  do_test autovacuum-2.5.2.1 {
   366    execsql {
   367      SELECT * FROM av1 WHERE a = 'av1 a';
   368    }
   369  } {{av1 a} {av1 b} {av1 c}}
   370  do_test autovacuum-2.5.2.2 {
   371    execsql {
   372      SELECT * FROM av2 WHERE a = 'av2 a' AND b = 'av2 b' AND c = 'av2 c'
   373    }
   374  } {{av2 a} {av2 b} {av2 c}}
   375  do_test autovacuum-2.5.2.3 {
   376    execsql {
   377      SELECT * FROM av3 WHERE a = 'av3 a' AND b = 'av3 b';
   378    }
   379  } {{av3 a} {av3 b} {av3 c}}
   380  do_test autovacuum-2.5.2.4 {
   381    execsql {
   382      SELECT * FROM av4 WHERE a = 'av4 a' AND b = 'av4 b' AND c = 'av4 c';
   383    }
   384  } {{av4 a} {av4 b} {av4 c}}
   385  
   386  # Drop table av3. Indices av4_i2, av4_i3 and av4_i4 are moved to fill the two
   387  # root pages vacated. The operation proceeds as:
   388  # Step 1: Delete av3_i1 (root-page 11). Move root-page of av4_i4 to page 11.
   389  # Step 2: Delete av3 (root-page 10). Move root-page of av4_i3 to page 10.
   390  # Step 3: Delete sqlite_autoindex_av1_3 (root-page 9). Move av4_i2 to page 9.
   391  do_test autovacuum-2.5.3 {
   392    execsql {
   393      DROP TABLE av3;
   394      SELECT name, rootpage FROM sqlite_master;
   395    }
   396  } [list av1 3  sqlite_autoindex_av1_1 4 \
   397          av2 5  sqlite_autoindex_av2_1 6 av2_i1 7 av2_i2 8 \
   398          av4 12 av4_i1 13 av4_i2 9 av4_i3 10 av4_i4 11 \
   399  ]
   400  do_test autovacuum-2.5.3.1 {
   401    execsql {
   402      SELECT * FROM av1 WHERE a = 'av1 a';
   403    }
   404  } {{av1 a} {av1 b} {av1 c}}
   405  do_test autovacuum-2.5.3.2 {
   406    execsql {
   407      SELECT * FROM av2 WHERE a = 'av2 a' AND b = 'av2 b' AND c = 'av2 c'
   408    }
   409  } {{av2 a} {av2 b} {av2 c}}
   410  do_test autovacuum-2.5.3.3 {
   411    execsql {
   412      SELECT * FROM av4 WHERE a = 'av4 a' AND b = 'av4 b' AND c = 'av4 c';
   413    }
   414  } {{av4 a} {av4 b} {av4 c}}
   415  
   416  # Drop table av1:
   417  # Step 1: Delete av1 (root page 4). Root-page of av4_i1 fills the gap.
   418  # Step 2: Delete sqlite_autoindex_av1_1 (root page 3). Move av4 to the gap.
   419  do_test autovacuum-2.5.4 {
   420    execsql {
   421      DROP TABLE av1;
   422      SELECT name, rootpage FROM sqlite_master;
   423    }
   424  } [list av2 5  sqlite_autoindex_av2_1 6 av2_i1 7 av2_i2 8 \
   425          av4 3 av4_i1 4 av4_i2 9 av4_i3 10 av4_i4 11 \
   426  ]
   427  do_test autovacuum-2.5.4.2 {
   428    execsql {
   429      SELECT * FROM av2 WHERE a = 'av2 a' AND b = 'av2 b' AND c = 'av2 c'
   430    }
   431  } {{av2 a} {av2 b} {av2 c}}
   432  do_test autovacuum-2.5.4.4 {
   433    execsql {
   434      SELECT * FROM av4 WHERE a = 'av4 a' AND b = 'av4 b' AND c = 'av4 c';
   435    }
   436  } {{av4 a} {av4 b} {av4 c}}
   437  
   438  # Drop table av4:
   439  # Step 1: Delete av4_i4.
   440  # Step 2: Delete av4_i3.
   441  # Step 3: Delete av4_i2.
   442  # Step 4: Delete av4_i1. av2_i2 replaces it.
   443  # Step 5: Delete av4. av2_i1 replaces it.
   444  do_test autovacuum-2.5.5 {
   445    execsql {
   446      DROP TABLE av4;
   447      SELECT name, rootpage FROM sqlite_master;
   448    }
   449  } [list av2 5 sqlite_autoindex_av2_1 6 av2_i1 3 av2_i2 4]
   450  do_test autovacuum-2.5.5.2 {
   451    execsql {
   452      SELECT * FROM av2 WHERE a = 'av2 a' AND b = 'av2 b' AND c = 'av2 c'
   453    }
   454  } {{av2 a} {av2 b} {av2 c}}
   455  
   456  #--------------------------------------------------------------------------
   457  # Test cases autovacuum-3.* test the operation of the "PRAGMA auto_vacuum"
   458  # command.
   459  #
   460  do_test autovacuum-3.1 {
   461    execsql {
   462      PRAGMA auto_vacuum;
   463    }
   464  } {1}
   465  do_test autovacuum-3.2 {
   466    db close
   467    sqlite3 db test.db
   468    execsql {
   469      PRAGMA auto_vacuum;
   470    }
   471  } {1}
   472  do_test autovacuum-3.3 {
   473    execsql {
   474      PRAGMA auto_vacuum = 0;
   475      PRAGMA auto_vacuum;
   476    }
   477  } {1}
   478  
   479  do_test autovacuum-3.4 {
   480    db close
   481    forcedelete test.db
   482    sqlite3 db test.db
   483    execsql {
   484      PRAGMA auto_vacuum;
   485    }
   486  } $AUTOVACUUM
   487  do_test autovacuum-3.5 {
   488    execsql {
   489      CREATE TABLE av1(x);
   490      PRAGMA auto_vacuum;
   491    }
   492  } $AUTOVACUUM
   493  do_test autovacuum-3.6 {
   494    execsql {
   495      PRAGMA auto_vacuum = 1;
   496      PRAGMA auto_vacuum;
   497    }
   498  } [expr $AUTOVACUUM ? 1 : 0]
   499  do_test autovacuum-3.7 {
   500    execsql {
   501      DROP TABLE av1;
   502    }
   503    file_pages
   504  } [expr $AUTOVACUUM?1:2]
   505  
   506  
   507  #-----------------------------------------------------------------------
   508  # Test that if a statement transaction around a CREATE INDEX statement is
   509  # rolled back no corruption occurs.
   510  #
   511  do_test autovacuum-4.0 {
   512    # The last round of tests may have left the db in non-autovacuum mode.
   513    # Reset everything just in case.
   514    #
   515    db close
   516    forcedelete test.db test.db-journal
   517    sqlite3 db test.db
   518    execsql {
   519      PRAGMA auto_vacuum = 1;
   520      PRAGMA auto_vacuum;
   521    }
   522  } {1}
   523  do_test autovacuum-4.1 {
   524    execsql {
   525      CREATE TABLE av1(a, b);
   526      BEGIN;
   527    }
   528    for {set i 0} {$i<100} {incr i} {
   529      execsql "INSERT INTO av1 VALUES($i, '[string repeat X 200]');"
   530    }
   531    execsql "INSERT INTO av1 VALUES(99, '[string repeat X 200]');"
   532    execsql {
   533      SELECT sum(a) FROM av1;
   534    }
   535  } {5049}
   536  do_test autovacuum-4.2 {
   537    catchsql {
   538      CREATE UNIQUE INDEX av1_i ON av1(a);
   539    }
   540  } {1 {UNIQUE constraint failed: av1.a}}
   541  do_test autovacuum-4.3 {
   542    execsql {
   543      SELECT sum(a) FROM av1;
   544    }
   545  } {5049}
   546  do_test autovacuum-4.4 {
   547    execsql {
   548      COMMIT;
   549    }
   550  } {}
   551  
   552  ifcapable integrityck {
   553  
   554  # Ticket #1727
   555  do_test autovacuum-5.1 {
   556    db close
   557    sqlite3 db :memory:
   558    db eval {
   559      PRAGMA auto_vacuum=1;
   560      CREATE TABLE t1(a);
   561      CREATE TABLE t2(a);
   562      DROP TABLE t1;
   563      PRAGMA integrity_check;
   564    }
   565  } ok
   566  
   567  }
   568  
   569  # Ticket #1728.
   570  #
   571  # In autovacuum mode, when tables or indices are deleted, the rootpage
   572  # values in the symbol table have to be updated.  There was a bug in this
   573  # logic so that if an index/table was moved twice, the second move might
   574  # not occur.  This would leave the internal symbol table in an inconsistent
   575  # state causing subsequent statements to fail.
   576  #
   577  # The problem is difficult to reproduce.  The sequence of statements in
   578  # the following test are carefully designed make it occur and thus to
   579  # verify that this very obscure bug has been resolved.
   580  # 
   581  ifcapable integrityck&&memorydb {
   582  
   583  do_test autovacuum-6.1 {
   584    db close
   585    sqlite3 db :memory:
   586    db eval {
   587      PRAGMA auto_vacuum=1;
   588      CREATE TABLE t1(a, b);
   589      CREATE INDEX i1 ON t1(a);
   590      CREATE TABLE t2(a);
   591      CREATE INDEX i2 ON t2(a);
   592      CREATE TABLE t3(a);
   593      CREATE INDEX i3 ON t2(a);
   594      CREATE INDEX x ON t1(b);
   595      DROP TABLE t3;
   596      PRAGMA integrity_check;
   597      DROP TABLE t2;
   598      PRAGMA integrity_check;
   599      DROP TABLE t1;
   600      PRAGMA integrity_check;
   601    }
   602  } {ok ok ok}
   603  
   604  }
   605  
   606  #---------------------------------------------------------------------
   607  # Test cases autovacuum-7.X test the case where a page must be moved
   608  # and the destination location collides with at least one other
   609  # entry in the page hash-table (internal to the pager.c module. 
   610  #
   611  do_test autovacuum-7.1 {
   612    db close
   613    forcedelete test.db
   614    forcedelete test.db-journal
   615    sqlite3 db test.db
   616  
   617    execsql {
   618      PRAGMA auto_vacuum=1;
   619      CREATE TABLE t1(a, b, PRIMARY KEY(a, b));
   620      INSERT INTO t1 VALUES(randstr(400,400),randstr(400,400));
   621      INSERT INTO t1 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 2
   622      INSERT INTO t1 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 4
   623      INSERT INTO t1 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 8
   624      INSERT INTO t1 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 16
   625      INSERT INTO t1 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 32
   626    }
   627  
   628    expr {[file size test.db] / 1024}
   629  } {73}
   630  
   631  do_test autovacuum-7.2 {
   632    execsql {
   633      CREATE TABLE t2(a, b, PRIMARY KEY(a, b));
   634      INSERT INTO t2 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 2
   635      CREATE TABLE t3(a, b, PRIMARY KEY(a, b));
   636      INSERT INTO t3 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 2
   637      CREATE TABLE t4(a, b, PRIMARY KEY(a, b));
   638      INSERT INTO t4 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 2
   639      CREATE TABLE t5(a, b, PRIMARY KEY(a, b));
   640      INSERT INTO t5 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 2
   641    }
   642    expr {[file size test.db] / 1024}
   643  } {354}
   644  
   645  do_test autovacuum-7.3 {
   646    db close
   647    sqlite3 db test.db
   648    execsql {
   649      BEGIN;
   650      DELETE FROM t4;
   651      COMMIT;
   652      SELECT count(*) FROM t1;
   653    }
   654    expr {[file size test.db] / 1024}
   655  } {286}
   656  
   657  #------------------------------------------------------------------------
   658  # Additional tests.
   659  #
   660  # Try to determine the autovacuum setting for a database that is locked.
   661  #
   662  do_test autovacuum-8.1 {
   663    db close
   664    sqlite3 db test.db
   665    sqlite3 db2 test.db
   666    db eval {PRAGMA auto_vacuum}
   667  } {1}
   668  if {[permutation] == ""} {
   669    do_test autovacuum-8.2 {
   670      db eval {BEGIN EXCLUSIVE}
   671      catchsql {PRAGMA auto_vacuum} db2
   672    } {1 {database is locked}}
   673    catch {db2 close}
   674    catch {db eval {COMMIT}}
   675  }
   676  
   677  do_test autovacuum-9.1 {
   678    execsql {
   679      DROP TABLE t1;
   680      DROP TABLE t2;
   681      DROP TABLE t3;
   682      DROP TABLE t4;
   683      DROP TABLE t5;
   684      PRAGMA page_count;
   685    }
   686  } {1}
   687  do_test autovacuum-9.2 {
   688    file size test.db
   689  } 1024
   690  do_test autovacuum-9.3 {
   691    execsql {
   692      CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
   693      INSERT INTO t1 VALUES(NULL, randstr(50,50));
   694    }
   695    for {set ii 0} {$ii < 10} {incr ii} {
   696      db eval { INSERT INTO t1 SELECT NULL, randstr(50,50) FROM t1 }
   697    }
   698    file size test.db
   699  } $::sqlite_pending_byte
   700  do_test autovacuum-9.4 {
   701    execsql { INSERT INTO t1 SELECT NULL, randstr(50,50) FROM t1 }
   702  } {}
   703  do_test autovacuum-9.5 {
   704    execsql { DELETE FROM t1 WHERE rowid > (SELECT max(a)/2 FROM t1) }
   705    file size test.db
   706  } $::sqlite_pending_byte
   707   
   708  do_execsql_test autovacuum-10.1 {
   709    DROP TABLE t1;
   710    CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
   711    INSERT INTO t1 VALUES(25, randomblob(104));
   712    REPLACE INTO t1 VALUES(25, randomblob(1117));
   713    PRAGMA integrity_check;
   714  } {ok}
   715  
   716  finish_test