CoolFace
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
incrvacuum.test893 linesDownload Raw Back to test
1# 2007 April 262#3# The author disclaims copyright to this source code.  In place of4# 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.  The12# focus of this file is testing the incremental vacuum feature.13#14# Note: There are also some tests for incremental vacuum and IO 15# errors in incrvacuum_ioerr.test.16#17# $Id: incrvacuum.test,v 1.23 2009/02/18 20:31:18 drh Exp $18 19set testdir [file dirname $argv0]20source $testdir/tester.tcl21 22# If this build of the library does not support auto-vacuum, omit this23# whole file.24ifcapable {!autovacuum || !pragma} {25  finish_test26  return27}28 29#---------------------------------------------------------------------30# Test the pragma on an empty database.31#32do_test incrvacuum-1.1 {33  execsql {34    pragma auto_vacuum;35  }36} $sqlite_options(default_autovacuum)37do_test incrvacuum-1.2.0 {38  # File size is sometimes 1 instead of 0 due to the hack we put in39  # to work around ticket #3260.  Search for comments on #3260 in40  # os_unix.c.41  expr {[file size test.db] > 1}42} {0}43do_test incrvacuum-1.2 {44  # This command will create the database.45  execsql {46    pragma auto_vacuum = 'full';47    pragma auto_vacuum;48  }49} {1}50do_test incrvacuum-1.2.1 {51  expr {[file size test.db] > 0}52} {1}53do_test incrvacuum-1.3 {54  execsql {55    pragma auto_vacuum = 'incremental';56    pragma auto_vacuum;57  }58} {2}59do_test incrvacuum-1.4 {60  # In this case the invalid value is ignored and the auto_vacuum61  # setting remains unchanged.62  execsql {63    pragma auto_vacuum = 'invalid';64    pragma auto_vacuum;65  }66} {2}67do_test incrvacuum-1.5 {68  execsql {69    pragma auto_vacuum = 1;70    pragma auto_vacuum;71  }72} {1}73do_test incrvacuum-1.6 {74  execsql {75    pragma auto_vacuum = '2';76    pragma auto_vacuum;77  }78} {2}79do_test incrvacuum-1.7 {80  # Invalid value. auto_vacuum setting remains unchanged.81  execsql {82    pragma auto_vacuum = 5;83    pragma auto_vacuum;84  }85} {2}86 87#---------------------------------------------------------------------88# Test the pragma on a non-empty database. It is possible to toggle89# the connection between "full" and "incremental" mode, but not to90# change from either of these to "none", or from "none" to "full" or91# "incremental".92#93do_test incrvacuum-2.1 {94  execsql {95    pragma auto_vacuum = 1;96    CREATE TABLE abc(a, b, c);97  }98} {}99do_test incrvacuum-2.2 {100  execsql {101    pragma auto_vacuum = 'none';102    pragma auto_vacuum;103  }104} {1}105do_test incrvacuum-2.2.1 {106  db close107  sqlite3 db test.db108  execsql {109    pragma auto_vacuum;110  }111} {1}112do_test incrvacuum-2.3 {113  execsql {114    pragma auto_vacuum = 'incremental';115    pragma auto_vacuum;116  }117} {2}118do_test incrvacuum-2.4 {119  execsql {120    pragma auto_vacuum = 'full';121    pragma auto_vacuum;122  }123} {1}124 125#---------------------------------------------------------------------126# Test that when the auto_vacuum mode is "incremental", the database127# does not shrink when pages are removed from it. But it does if128# the mode is set to "full".129#130do_test incrvacuum-3.1 {131  execsql {132    pragma auto_vacuum;133  }134} {1}135do_test incrvacuum-3.2 {136  set ::str [string repeat 1234567890 110]137  execsql {138    PRAGMA auto_vacuum = 2;139    BEGIN;140    CREATE TABLE tbl2(str);141    INSERT INTO tbl2 VALUES($::str);142    COMMIT;143  }144  # 5 pages:145  #146  #   1 -> database header147  #   2 -> first back-pointer page148  #   3 -> table abc149  #   4 -> table tbl2150  #   5 -> table tbl2 overflow page.151  #152  expr {[file size test.db] / 1024}153} {5}154do_test incrvacuum-3.3 {155  execsql {156    DROP TABLE abc;157    DELETE FROM tbl2;158  }159  expr {[file size test.db] / 1024}160} {5}161do_test incrvacuum-3.4 {162  execsql {163    PRAGMA auto_vacuum = 1;164    INSERT INTO tbl2 VALUES('hello world');165  }166  expr {[file size test.db] / 1024}167} {3}168 169#---------------------------------------------------------------------170# Try to run a very simple incremental vacuum. Also verify that 171# PRAGMA incremental_vacuum is a harmless no-op against a database that172# does not support auto-vacuum.173#174do_test incrvacuum-4.1 {175  set ::str [string repeat 1234567890 110]176  execsql {177    PRAGMA auto_vacuum = 2;178    INSERT INTO tbl2 VALUES($::str);179    CREATE TABLE tbl1(a, b, c);180  }181  expr {[file size test.db] / 1024}182} {5}183do_test incrvacuum-4.2 {184  execsql {185    DELETE FROM tbl2;186    DROP TABLE tbl1;187  }188  expr {[file size test.db] / 1024}189} {5}190do_test incrvacuum-4.3 {191  set ::nStep 0192  db eval {pragma incremental_vacuum(10)} {193    incr ::nStep194  }195  list [expr {[file size test.db] / 1024}] $::nStep196} {3 2}197 198#---------------------------------------------------------------------199# The following tests - incrvacuum-5.* - test incremental vacuum200# from within a transaction.201#202do_test incrvacuum-5.1.1 {203  expr {[file size test.db] / 1024}204} {3}205do_test incrvacuum-5.1.2 {206  execsql {207    BEGIN;208    DROP TABLE tbl2;209    PRAGMA incremental_vacuum;210    COMMIT;211  }212  expr {[file size test.db] / 1024}213} {1}214 215do_test incrvacuum-5.2.1 {216  set ::str [string repeat abcdefghij 110]217  execsql {218    BEGIN;219    CREATE TABLE tbl1(a);220    INSERT INTO tbl1 VALUES($::str);221    PRAGMA incremental_vacuum;                 -- this is a no-op.222    COMMIT;223  }224  expr {[file size test.db] / 1024}225} {4}226do_test incrvacuum-5.2.2 {227  set ::str [string repeat abcdefghij 110]228  execsql {229    BEGIN;230    INSERT INTO tbl1 VALUES($::str);231    INSERT INTO tbl1 SELECT * FROM tbl1;232    DELETE FROM tbl1 WHERE oid%2;        -- Put 2 overflow pages on free-list.233    COMMIT;234  }235  expr {[file size test.db] / 1024}236} {7}237do_test incrvacuum-5.2.3 {238  execsql {239    BEGIN;240    PRAGMA incremental_vacuum;           -- Vacuum up the two pages.241    CREATE TABLE tbl2(b);                -- Use one free page as a table root.242    INSERT INTO tbl2 VALUES('a nice string');243    COMMIT;244  }245  expr {[file size test.db] / 1024}246} {6}247do_test incrvacuum-5.2.4 {248  execsql {249    SELECT * FROM tbl2;250  }251} {{a nice string}}252do_test incrvacuum-5.2.5 {253  execsql {254    DROP TABLE tbl1;255    DROP TABLE tbl2;256    PRAGMA incremental_vacuum;257  }258  expr {[file size test.db] / 1024}259} {1}260 261 262# Test cases incrvacuum-5.3.* use the following list as input data.263# Two new databases are opened, one with incremental vacuum enabled,264# the other with no auto-vacuum completely disabled. After executing265# each element of the following list on both databases, test that266# the integrity-check passes and the contents of each are identical.267# 268set TestScriptList [list {269  BEGIN;270  CREATE TABLE t1(a, b);271  CREATE TABLE t2(a, b);272  CREATE INDEX t1_i ON t1(a);273  CREATE INDEX t2_i ON t2(a);274} {275  INSERT INTO t1 VALUES($::str1, $::str2);276  INSERT INTO t1 VALUES($::str1||$::str2, $::str2||$::str1);277  INSERT INTO t2 SELECT b, a FROM t1;278  INSERT INTO t2 SELECT a, b FROM t1;279  INSERT INTO t1 SELECT b, a FROM t2;280  UPDATE t2 SET b = '';281  PRAGMA incremental_vacuum;282} {283  UPDATE t2 SET b = (SELECT b FROM t1 WHERE t1.oid = t2.oid);284  PRAGMA incremental_vacuum;285} {286  CREATE TABLE t3(a, b);287  INSERT INTO t3 SELECT * FROM t2;288  DROP TABLE t2;289  PRAGMA incremental_vacuum;290} {291  CREATE INDEX t3_i ON t3(a);292  COMMIT;293} {294  BEGIN;295  DROP INDEX t3_i;296  PRAGMA incremental_vacuum;297  INSERT INTO t3 VALUES('hello', 'world');298  ROLLBACK;299} {300  INSERT INTO t3 VALUES('hello', 'world');301}302]303 304# If this build omits subqueries, step 2 in the above list will not305# work. Replace it with "" in this case. 306#307ifcapable !subquery { lset TestScriptList 2 "" }308 309# Compare the contents of databases $A and $B.310#311proc compare_dbs {A B tname} {312  set tbl_list [execsql {313    SELECT tbl_name FROM sqlite_master WHERE type = 'table'314  } $A]315 316  do_test ${tname}.1 [subst {317    execsql {318      SELECT tbl_name FROM sqlite_master WHERE type = 'table'319    } $B320  }] $tbl_list321 322  set tn 1323  foreach tbl $tbl_list {324    set control [execsql "SELECT * FROM $tbl" $A]325    do_test ${tname}.[incr tn] [subst {326      execsql "SELECT * FROM $tbl" $B327    }] $control328  }329}330 331set ::str1 [string repeat abcdefghij 130]332set ::str2 [string repeat 1234567890 105]333 334forcedelete test1.db test1.db-journal test2.db test2.db-journal335sqlite3 db1 test1.db336sqlite3 db2 test2.db337execsql { PRAGMA auto_vacuum = 'none' } db1338execsql { PRAGMA auto_vacuum = 'incremental' } db2339 340set tn 1341foreach sql $::TestScriptList {342  execsql $sql db1343  execsql $sql db2344 345  compare_dbs db1 db2 incrvacuum-5.3.${tn}346  do_test incrvacuum-5.3.${tn}.integrity1 {347    execsql { PRAGMA integrity_check; } db1348  } {ok}349  do_test incrvacuum-5.3.${tn}.integrity2 {350    execsql { PRAGMA integrity_check; } db2351  } {ok}352  incr tn353}354db1 close355db2 close356#357# End of test cases 5.3.*358 359#---------------------------------------------------------------------360# The following tests - incrvacuum-6.* - test running incremental 361# vacuum while another statement (a read) is being executed.362#363for {set jj 0} {$jj < 10} {incr jj} {364  # Build some test data. Two tables are created in an empty365  # database. tbl1 data is a contiguous block starting at page 5 (pages366  # 3 and 4 are the table roots). tbl2 is a contiguous block starting 367  # right after tbl1.368  #369  # Then drop tbl1 so that when an incr vacuum is run the pages370  # of tbl2 have to be moved to fill the gap.371  #372  do_test incrvacuum-6.${jj}.1 {373    execsql {374      DROP TABLE IF EXISTS tbl1;375      DROP TABLE IF EXISTS tbl2;376      PRAGMA incremental_vacuum;377      CREATE TABLE tbl1(a, b);378      CREATE TABLE tbl2(a, b);379      BEGIN;380    }381    for {set ii 0} {$ii < 1000} {incr ii} {382      db eval {INSERT INTO tbl1 VALUES($ii, $ii || $ii)}383    }384    execsql {385      INSERT INTO tbl2 SELECT * FROM tbl1;386      COMMIT;387      DROP TABLE tbl1;388    }389    expr {[file size test.db] / 1024}390  } {36}391 392  # Run a linear scan query on tbl2. After reading ($jj*100) rows, 393  # run the incremental vacuum to shrink the database.394  #395  do_test incrvacuum-6.${jj}.2 {396    set ::nRow 0397    db eval {SELECT a FROM tbl2} {} {398      if {$a == [expr $jj*100]} {399        db eval {PRAGMA incremental_vacuum}400      }401      incr ::nRow402    }403    list [expr {[file size test.db] / 1024}] $nRow404  } {19 1000}405}406 407#---------------------------------------------------------------------408# This test - incrvacuum-7.* - is to check that the database can be409# written in the middle of an incremental vacuum.410#411set ::iWrite 1412while 1 {413  do_test incrvacuum-7.${::iWrite}.1 {414    execsql {415      DROP TABLE IF EXISTS tbl1;416      DROP TABLE IF EXISTS tbl2;417      PRAGMA incremental_vacuum;418      CREATE TABLE tbl1(a, b);419      CREATE TABLE tbl2(a, b);420      BEGIN;421    }422    for {set ii 0} {$ii < 1000} {incr ii} {423      db eval {INSERT INTO tbl1 VALUES($ii, $ii || $ii)}424    }425    execsql {426      INSERT INTO tbl2 SELECT * FROM tbl1;427      COMMIT;428      DROP TABLE tbl1;429    }430    expr {[file size test.db] / 1024}431  } {36}432 433  do_test incrvacuum-7.${::iWrite}.2 {434    set ::nRow 0435    db eval {PRAGMA incremental_vacuum} {436      incr ::nRow437      if {$::nRow == $::iWrite} {438        db eval {439          CREATE TABLE tbl1(a, b);440          INSERT INTO tbl1 VALUES('hello', 'world');441        }442      }443    }444    list [expr {[file size test.db] / 1024}]445  } {20}446 447  do_test incrvacuum-7.${::iWrite}.3 {448    execsql {449      SELECT * FROM tbl1;450    }451  } {hello world}452 453  if {$::nRow == $::iWrite} break454  incr ::iWrite455}456 457#---------------------------------------------------------------------458# This test - incrvacuum-8.* - is to check that nothing goes wrong459# with an incremental-vacuum if it is the first statement executed460# after an existing database is opened.461#462# At one point, this would always return SQLITE_SCHEMA (which 463# causes an infinite loop in tclsqlite.c if using the Tcl interface).464#465do_test incrvacuum-8.1 {466  db close467  sqlite3 db test.db468  execsql {469    PRAGMA incremental_vacuum(50);470  }471} {}472 473#---------------------------------------------------------------------474# At one point this test case was causing an assert() to fail.475#476do_test incrvacuum-9.1 {477  db close478  forcedelete test.db test.db-journal479  sqlite3 db test.db480 481  execsql {482    PRAGMA auto_vacuum = 'incremental';483    CREATE TABLE t1(a, b, c);484    CREATE TABLE t2(a, b, c);485    INSERT INTO t2 VALUES(randstr(500,500),randstr(500,500),randstr(500,500));486    INSERT INTO t1 VALUES(1, 2, 3);487    INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;488    INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;489    INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;490    INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;491    INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;492    INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;493    INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;494    INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;495  }496} {}497 498do_test incrvacuum-9.2 {499  execsql {500    PRAGMA synchronous = 'OFF';501    BEGIN;502    UPDATE t1 SET a = a, b = b, c = c;503    DROP TABLE t2;504    PRAGMA incremental_vacuum(10);505    ROLLBACK;506  }507} {}508 509do_test incrvacuum-9.3 {510  execsql {511    PRAGMA cache_size = 10;512    BEGIN;513    UPDATE t1 SET a = a, b = b, c = c;514    DROP TABLE t2;515    PRAGMA incremental_vacuum(10);516    ROLLBACK;517  }518} {}519 520#---------------------------------------------------------------------521# Test that the parameter to the incremental_vacuum pragma works. That522# is, if the user executes "PRAGMA incremental_vacuum(N)", at most523# N pages are vacuumed.524#525do_test incrvacuum-10.1 {526  execsql {527    DROP TABLE t1;528    DROP TABLE t2;529  }530  expr [file size test.db] / 1024531} {29}532 533do_test incrvacuum-10.2 {534  execsql {535    PRAGMA incremental_vacuum(1);536  }537  expr [file size test.db] / 1024538} {28}539 540do_test incrvacuum-10.3 {541  execsql {542    PRAGMA incremental_vacuum(5);543  }544  expr [file size test.db] / 1024545} {23}546 547do_test incrvacuum-10.4 {548  execsql {549    PRAGMA incremental_vacuum('1');550  }551  expr [file size test.db] / 1024552} {22}553 554do_test incrvacuum-10.5 {555  execsql {556    PRAGMA incremental_vacuum("+3");557  }558  expr [file size test.db] / 1024559} {19}560 561do_test incrvacuum-10.6 {562  execsql {563    PRAGMA incremental_vacuum = 1;564  }565  expr [file size test.db] / 1024566} {18}567 568do_test incrvacuum-10.7 {569  # Use a really big number as an argument to incremetal_vacuum. Should570  # be interpreted as "free all possible space".571  execsql {572    PRAGMA incremental_vacuum(2147483649);573  }574  expr [file size test.db] / 1024575} {1}576 577do_test incrvacuum-10.8 {578  execsql {579    CREATE TABLE t1(x);580    INSERT INTO t1 VALUES(hex(randomblob(1000)));581    DROP TABLE t1;582  }583  # A negative number means free all possible space.584  execsql {585    PRAGMA incremental_vacuum=-1;586  }587  expr [file size test.db] / 1024588} {1}589 590#----------------------------------------------------------------591# Test that if we set the auto_vacuum mode to 'incremental', then592# create a database, thereafter that database defaults to incremental 593# vacuum mode.594#595db close596forcedelete test.db test.db-journal597sqlite3 db test.db598 599ifcapable default_autovacuum {600  do_test incrvacuum-11.1-av-dflt-on {601    execsql {602      PRAGMA auto_vacuum;603    }604  } $AUTOVACUUM605} else {606  do_test incrvacuum-11.1-av-dflt-off {607    execsql {608      PRAGMA auto_vacuum;609    }610  } {0}611}612do_test incrvacuum-11.2 {613  execsql {614    PRAGMA auto_vacuum = incremental;615  }616} {}617do_test incrvacuum-11.3 {618  execsql {619    PRAGMA auto_vacuum;620  }621} {2}622do_test incrvacuum-11.4 {623  # The database has now been created.624  expr {[file size test.db]>0}625} {1}626do_test incrvacuum-11.5 {627  # Close and reopen the connection.628  db close629  sqlite3 db test.db630 631  # Test we are still in incremental vacuum mode.632  execsql { PRAGMA auto_vacuum; }633} {2}634do_test incrvacuum-11.6 {635  execsql {636    PRAGMA auto_vacuum = 'full';637    PRAGMA auto_vacuum;638  }639} {1}640do_test incrvacuum-11.7 {641  # Close and reopen the connection.642  db close643  sqlite3 db test.db644 645  # Test we are still in "full" auto-vacuum mode.646  execsql { PRAGMA auto_vacuum; }647} {1}648 649#----------------------------------------------------------------------650# Special case: What happens if the database is locked when a "PRAGMA651# auto_vacuum = XXX" statement is executed.652#653db close654forcedelete test.db test.db-journal655sqlite3 db test.db656 657do_test incrvacuum-12.1 {658  execsql {659    PRAGMA auto_vacuum = 1;660  }661  expr {[file size test.db]>0}662} {1}663 664# Try to change the auto-vacuum from "full" to "incremental" while the665# database is locked. Nothing should change.666#667do_test incrvacuum-12.2 {668  sqlite3 db2 test.db669  execsql { BEGIN EXCLUSIVE; } db2670  catchsql { PRAGMA auto_vacuum = 2; }671} {1 {database is locked}}672 673do_test incrvacuum-12.3 {674  execsql { ROLLBACK; } db2675  execsql { PRAGMA auto_vacuum }676} {2}   ;# Still 2 because PRAGMA auto_vacuum setting held in case of vacuum677do_test incrvacuum-12.4 {678  db close679  sqlite3 db test.db680  execsql { PRAGMA auto_vacuum }681} {1}   ;# Revert to 1 because the database file did not change682 683do_test incrvacuum-12.5 {684  execsql { SELECT * FROM sqlite_master }685  execsql { PRAGMA auto_vacuum }686} {1}687 688#----------------------------------------------------------------------689# Special case #2: What if one process prepares a "PRAGMA auto_vacuum = XXX"690# statement when the database is empty, but doesn't execute it until691# after some other process has created the database.692#693db2 close694db close695forcedelete test.db test.db-journal696sqlite3 db test.db  ;  set ::DB [sqlite3_connection_pointer db]697sqlite3 db2 test.db698 699do_test incrvacuum-13.1 {700  # File size is sometimes 1 instead of 0 due to the hack we put in701  # to work around ticket #3260.  Search for comments on #3260 in702  # os_unix.c.703  expr {[file size test.db]>1}704} {0}705do_test incrvacuum-13.2 {706  set ::STMT [sqlite3_prepare $::DB {PRAGMA auto_vacuum = 2} -1 DUMMY]707  execsql {708    PRAGMA auto_vacuum = none;709    PRAGMA default_cache_size = 1024;710    PRAGMA auto_vacuum;711  } db2712} {0}713do_test incrvacuum-13.3 {714  expr {[file size test.db]>0}715} {1}716do_test incrvacuum-13.4 {717  set rc [sqlite3_step $::STMT]718  list $rc [sqlite3_finalize $::STMT]719} {SQLITE_DONE SQLITE_OK}720do_test incrvacuum-13.5 {721  execsql {722    PRAGMA auto_vacuum;723  }724} {0}725 726 727# Verify that the incremental_vacuum pragma fails gracefully if it728# is used against an invalid database file.729#730if {[permutation] == ""} {731  do_test incrvacuum-14.1 {732    set out [open invalid.db w]733    puts $out "This is not an SQLite database file"734    close $out735    sqlite3 db3 invalid.db736    catchsql {737      PRAGMA incremental_vacuum(10);738    } db3739  } {1 {file is not a database}}740  db3 close741}742 743do_test incrvacuum-15.1 {744  db close745  db2 close746  forcedelete test.db747  sqlite3 db test.db748 749  set str [string repeat "abcdefghij" 500]750 751  execsql {752    PRAGMA cache_size = 10;753    PRAGMA auto_vacuum = incremental;754    CREATE TABLE t1(x, y);755    INSERT INTO t1 VALUES('a', $str);756    INSERT INTO t1 VALUES('b', $str);757    INSERT INTO t1 VALUES('c', $str);758    INSERT INTO t1 VALUES('d', $str);759    INSERT INTO t1 VALUES('e', $str);760    INSERT INTO t1 VALUES('f', $str);761    INSERT INTO t1 VALUES('g', $str);762    INSERT INTO t1 VALUES('h', $str);763    INSERT INTO t1 VALUES('i', $str);764    INSERT INTO t1 VALUES('j', $str);765    INSERT INTO t1 VALUES('j', $str);766 767    CREATE TABLE t2(x PRIMARY KEY, y);768    INSERT INTO t2 VALUES('a', $str);769    INSERT INTO t2 VALUES('b', $str);770    INSERT INTO t2 VALUES('c', $str);771    INSERT INTO t2 VALUES('d', $str);772 773    BEGIN;774      DELETE FROM t2;775      PRAGMA incremental_vacuum;776  }777 778  catchsql {INSERT INTO t2 SELECT * FROM t1}779 780  execsql { 781    COMMIT;782    PRAGMA integrity_check;783  }784} {ok}785 786#-------------------------------------------------------------------------787# At one point it was unsafe to truncate a db file on windows while there788# were outstanding xFetch() references. This test case attempts to hit789# that case.790#791ifcapable mmap {792  reset_db793  do_execsql_test incrvacuum-16.0 {794    PRAGMA auto_vacuum = 2;795    CREATE TABLE t3(a);796    INSERT INTO t3 VALUES(1), (2), (3), (4);797  798    CREATE TABLE t2(x);799    INSERT INTO t2 VALUES( randomblob(1000) );800    INSERT INTO t2 VALUES( randomblob(1000) );801    INSERT INTO t2 VALUES( randomblob(1000) );802    INSERT INTO t2 VALUES( randomblob(1000) );803    INSERT INTO t2 VALUES( randomblob(1000) );804    INSERT INTO t2 VALUES( randomblob(1000) );805  } {}806  807  # Reopen db to ensure the page-cache is empty.808  #809  db close810  sqlite3 db test.db811  812  # Open db in mmap-mode. Open a transaction, delete some data, then run813  # incremental-vacuum. Do not commit the transaction. 814  #815  do_execsql_test incrvacuum-16.1 {816    PRAGMA mmap_size = 1000000;817    BEGIN;818    DELETE FROM t2;819    PRAGMA incremental_vacuum = 1000;820  } {1000000}821 822  # Scan through table t3 (which is all clean pages - so mmap is used). Then,823  # midway through, commit the transaction. This causes the db to be truncated824  # while there are outstanding xFetch pages.825  #826  do_test incrvacuum-16.2 {827    set res [list]828    db eval { SELECT a FROM t3 } {829      if {$a==3} { db eval COMMIT }830      lappend res $a831    }832    set res833  } {1 2 3 4}834}835 836# 2021-04-05 dbsqlfuzz cced0668cfd4da4eb2382cb9dd26c17c64aaff76837#838# This is an incremental vacuum database that has one free page that839# needs to be filled.  After removing the last page from the end of840# the database file to fill the free page slot, the last page that841# is left is the tail of an overflow chain.842#843# But the size of the database file is shorter than the actual data844# so that after incremental vacuum runs, the file is actually too845# small to hold the last page of the overflow chain.846#847# At one point this caused an assertion fault in 848# sqlite3PagerTruncateImage().849#850do_test incrvacuum-17.0 {851  sqlite3 db {}852  database_may_be_corrupt853  db deserialize [decode_hexdb {854| size 20480 pagesize 4096 filename x2.db855| page 1 offset 0856|      0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00   SQLite format 3.857|     16: 10 00 01 01 00 40 20 20 00 00 00 05 00 00 00 07   .....@  ........858|     32: 00 00 00 04 00 00 00 01 00 00 00 03 00 00 00 04   ................859|     48: 00 00 00 00 00 00 00 03 00 00 00 01 00 00 00 00   ................860|     64: 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00   ................861|     80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05   ................862|     96: 00 2e 53 60 0d 0f dc 00 01 0f b8 00 0f b8 0f b8   ..S`............863|   4016: 00 00 00 00 00 00 00 00 22 02 06 17 11 11 01 31   ...............1864|   4032: 74 61 62 6c 65 74 32 74 32 03 43 52 45 41 54 45   tablet2t2.CREATE865|   4048: 20 54 41 42 4c 45 20 74 32 28 79 29 00 00 00 24    TABLE t2(y)...$866|   4064: 11 11 01 31 74 61 62 6c 65 74 31 74 31 03 43 52   ...1tablet1t1.CR867|   4080: 45 41 54 45 20 54 41 42 4c 45 20 74 31 28 78 29   EATE TABLE t1(x)868| page 2 offset 4096869|      0: 01 00 00 00 00 02 00 00 00 00 03 00 00 00 03 04   ................870|     16: 00 00 00 05 03 00 00 00 03 00 00 00 00 00 00 00   ................871| page 3 offset 8192872|      0: 0d 00 00 00 02 05 47 00 08 dd 05 47 00 00 00 00   ......G....G....873|   1344: 00 00 00 00 00 00 00 a7 0b 02 03 ce 1c 00 00 00   ................874|   2256: 00 00 00 00 00 00 00 00 00 00 00 00 07 ce 14 01   ................875|   2272: 04 81 9c 2c 00 00 00 00 00 00 00 00 00 00 00 00   ...,............876|   4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05   ................877| page 4 offset 12288878|      0: 00 00 00 00 00 00 00 00 08 dd 05 47 00 00 00 00   ...........G....879|   1344: 00 00 00 00 00 00 00 a7 0b 02 03 ce 1c 00 00 00   ................880|   2256: 00 00 00 00 00 00 00 00 00 00 00 00 07 ce 14 01   ................881|   2272: 04 81 9c 2c 00 00 00 00 00 00 00 00 00 00 00 00   ...,............882|   4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05   ................883| page 5 offset 16384884|      0: 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 00   ................885| end x2.db886}]} {}887do_catchsql_test incrvacuum-17.1 {888  PRAGMA writable_schema=ON;889  PRAGMA incremental_vacuum(10);890} {0 {}}891 892finish_test893