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

     1  # 2007 August 21
     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  #
    12  # The focus of this file is testing some specific characteristics of the 
    13  # IO traffic generated by SQLite (making sure SQLite is not writing out
    14  # more database pages than it has to, stuff like that).
    15  #
    16  
    17  set testdir [file dirname $argv0]
    18  source $testdir/tester.tcl
    19  set ::testprefix io
    20  
    21  db close
    22  sqlite3_simulate_device
    23  sqlite3 db test.db -vfs devsym
    24  
    25  # Test summary:
    26  #
    27  # io-1.* -  Test that quick-balance does not journal pages unnecessarily.
    28  #
    29  # io-2.* -  Test the "atomic-write optimization".
    30  #
    31  # io-3.* -  Test the IO traffic enhancements triggered when the 
    32  #           IOCAP_SEQUENTIAL device capability flag is set (no 
    33  #           fsync() calls on the journal file).
    34  #
    35  # io-4.* -  Test the IO traffic enhancements triggered when the 
    36  #           IOCAP_SAFE_APPEND device capability flag is set (fewer 
    37  #           fsync() calls on the journal file, no need to set nRec
    38  #           field in the single journal header).
    39  #
    40  # io-5.* -  Test that the default page size is selected and used 
    41  #           correctly.
    42  #
    43  # io-6.* -  Test that the pager-cache is not being flushed unnecessarily 
    44  #           after a transaction that uses the special atomic-write path
    45  #           is committed.
    46  #           
    47  
    48  set ::nWrite 0
    49  proc nWrite {db} {
    50    set bt [btree_from_db $db]
    51    db_enter $db
    52    array set stats [btree_pager_stats $bt]
    53    db_leave $db
    54    set res [expr $stats(write) - $::nWrite]
    55    set ::nWrite $stats(write)
    56    set res
    57  }
    58  
    59  set ::nSync 0
    60  proc nSync {} {
    61    set res [expr {$::sqlite_sync_count - $::nSync}]
    62    set ::nSync $::sqlite_sync_count
    63    set res
    64  }
    65  
    66  do_test io-1.1 {
    67    execsql {
    68      PRAGMA auto_vacuum = OFF;
    69      PRAGMA page_size = 1024;
    70      CREATE TABLE abc(a,b);
    71    }
    72    nWrite db
    73  } {2}
    74  
    75  # Insert into the table 4 records of aproximately 240 bytes each.
    76  # This should completely fill the root-page of the table. Each
    77  # INSERT causes 2 db pages to be written - the root-page of "abc"
    78  # and page 1 (db change-counter page).
    79  do_test io-1.2 {
    80    set ret [list]
    81    execsql { INSERT INTO abc VALUES(1,randstr(230,230)); }
    82    lappend ret [nWrite db]
    83    execsql { INSERT INTO abc VALUES(2,randstr(230,230)); }
    84    lappend ret [nWrite db]
    85    execsql { INSERT INTO abc VALUES(3,randstr(230,230)); }
    86    lappend ret [nWrite db]
    87    execsql { INSERT INTO abc VALUES(4,randstr(230,230)); }
    88    lappend ret [nWrite db]
    89  } {2 2 2 2}
    90  
    91  # Insert another 240 byte record. This causes two leaf pages
    92  # to be added to the root page of abc. 4 pages in total
    93  # are written to the db file - the two leaf pages, the root
    94  # of abc and the change-counter page.
    95  do_test io-1.3 {
    96    execsql { INSERT INTO abc VALUES(5,randstr(230,230)); }
    97    nWrite db
    98  } {4}
    99  
   100  # Insert another 3 240 byte records. After this, the tree consists of 
   101  # the root-node, which is close to empty, and two leaf pages, both of 
   102  # which are full. 
   103  do_test io-1.4 {
   104    set ret [list]
   105    execsql { INSERT INTO abc VALUES(6,randstr(230,230)); }
   106    lappend ret [nWrite db]
   107    execsql { INSERT INTO abc VALUES(7,randstr(230,230)); }
   108    lappend ret [nWrite db]
   109    execsql { INSERT INTO abc VALUES(8,randstr(230,230)); }
   110    lappend ret [nWrite db]
   111  } {2 2 2}
   112  
   113  # This insert should use the quick-balance trick to add a third leaf
   114  # to the b-tree used to store table abc. It should only be necessary to
   115  # write to 3 pages to do this: the change-counter, the root-page and
   116  # the new leaf page.
   117  do_test io-1.5 {
   118    execsql { INSERT INTO abc VALUES(9,randstr(230,230)); }
   119    nWrite db
   120  } {3}
   121  
   122  ifcapable atomicwrite {
   123  
   124  #----------------------------------------------------------------------
   125  # Test cases io-2.* test the atomic-write optimization.
   126  #
   127  do_test io-2.1 {
   128    execsql { DELETE FROM abc; VACUUM; }
   129  } {}
   130  
   131  # Clear the write and sync counts.
   132  nWrite db ; nSync
   133  
   134  # The following INSERT updates 2 pages and requires 4 calls to fsync():
   135  #
   136  #   1) The directory in which the journal file is created,
   137  #   2) The journal file (to sync the page data),
   138  #   3) The journal file (to sync the journal file header),
   139  #   4) The database file.
   140  #
   141  do_test io-2.2 {
   142    execsql { INSERT INTO abc VALUES(1, 2) }
   143    list [nWrite db] [nSync]
   144  } {2 4}
   145  
   146  # Set the device-characteristic mask to include the SQLITE_IOCAP_ATOMIC,
   147  # then do another INSERT similar to the one in io-2.2. This should
   148  # only write 1 page and require a single fsync().
   149  # 
   150  # The single fsync() is the database file. Only one page is reported as
   151  # written because page 1 - the change-counter page - is written using
   152  # an out-of-band method that bypasses the write counter.
   153  #
   154  # UPDATE: As of [05f98d4eec] (adding SQLITE_DBSTATUS_CACHE_WRITE), the
   155  # second write is also counted. So this now reports two writes and a
   156  # single fsync.
   157  #
   158  sqlite3_simulate_device -char atomic
   159  do_test io-2.3 {
   160    execsql { INSERT INTO abc VALUES(3, 4) }
   161    list [nWrite db] [nSync]
   162  } {2 1}
   163  
   164  # Test that the journal file is not created and the change-counter is
   165  # updated when the atomic-write optimization is used.
   166  #
   167  do_test io-2.4.1 {
   168    execsql {
   169      BEGIN;
   170      INSERT INTO abc VALUES(5, 6);
   171    }
   172    sqlite3 db2 test.db -vfs devsym
   173    execsql { SELECT * FROM abc } db2
   174  } {1 2 3 4}
   175  do_test io-2.4.2 {
   176    file exists test.db-journal
   177  } {0}
   178  do_test io-2.4.3 {
   179    execsql { COMMIT }
   180    execsql { SELECT * FROM abc } db2
   181  } {1 2 3 4 5 6}
   182  db2 close
   183  
   184  # Test that the journal file is created and sync()d if the transaction
   185  # modifies more than one database page, even if the IOCAP_ATOMIC flag
   186  # is set.
   187  #
   188  do_test io-2.5.1 {
   189    execsql { CREATE TABLE def(d, e) }
   190    nWrite db ; nSync
   191    execsql {
   192      BEGIN;
   193      INSERT INTO abc VALUES(7, 8);
   194    }
   195    file exists test.db-journal
   196  } {0}
   197  do_test io-2.5.2 {
   198    execsql { INSERT INTO def VALUES('a', 'b'); }
   199    file exists test.db-journal
   200  } {1}
   201  do_test io-2.5.3 {
   202    execsql { COMMIT }
   203    list [nWrite db] [nSync]
   204  } {3 4}
   205  
   206  # Test that the journal file is created and sync()d if the transaction
   207  # modifies a single database page and also appends a page to the file.
   208  # Internally, this case is handled differently to the one above. The
   209  # journal file is not actually created until the 'COMMIT' statement
   210  # is executed.
   211  #
   212  # Changed 2010-03-27:  The size of the database is now stored in 
   213  # bytes 28..31 and so when a page is added to the database, page 1
   214  # is immediately modified and the journal file immediately comes into
   215  # existence.  To fix this test, the BEGIN is changed into a a
   216  # BEGIN IMMEDIATE and the INSERT is omitted.
   217  #
   218  do_test io-2.6.1 {
   219    execsql {
   220      BEGIN IMMEDIATE;
   221      -- INSERT INTO abc VALUES(9, randstr(1000,1000));
   222    }
   223    file exists test.db-journal
   224  } {0}
   225  do_test io-2.6.2 {
   226    # Create a file at "test.db-journal". This will prevent SQLite from
   227    # opening the journal for exclusive access. As a result, the COMMIT
   228    # should fail with SQLITE_CANTOPEN and the transaction rolled back.
   229    #
   230    file mkdir test.db-journal
   231    catchsql {
   232      INSERT INTO abc VALUES(9, randstr(1000,1000));
   233      COMMIT
   234    }
   235  } {1 {unable to open database file}}
   236  do_test io-2.6.3 {
   237    forcedelete test.db-journal
   238    catchsql { COMMIT }
   239  } {0 {}}
   240  do_test io-2.6.4 {
   241    execsql { SELECT * FROM abc }
   242  } {1 2 3 4 5 6 7 8}
   243  
   244  # Test that if the database modification is part of multi-file commit,
   245  # the journal file is always created. In this case, the journal file
   246  # is created during execution of the COMMIT statement, so we have to
   247  # use the same technique to check that it is created as in the above 
   248  # block.
   249  forcedelete test2.db test2.db-journal
   250  ifcapable attach {
   251    do_test io-2.7.1 {
   252      execsql {
   253        ATTACH 'test2.db' AS aux;
   254        PRAGMA aux.page_size = 1024;
   255        CREATE TABLE aux.abc2(a, b);
   256        BEGIN;
   257        INSERT INTO abc VALUES(9, 10);
   258      }
   259      file exists test.db-journal
   260    } {0}
   261    do_test io-2.7.2 {
   262      execsql { INSERT INTO abc2 SELECT * FROM abc }
   263      file exists test2.db-journal
   264    } {0}
   265    do_test io-2.7.3 {
   266      execsql { SELECT * FROM abc UNION ALL SELECT * FROM abc2 }
   267    } {1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10}
   268    do_test io-2.7.4 {
   269      file mkdir test2.db-journal
   270      catchsql { COMMIT }
   271    } {1 {unable to open database file}}
   272    do_test io-2.7.5 {
   273      forcedelete test2.db-journal
   274      catchsql { COMMIT }
   275    } {1 {cannot commit - no transaction is active}}
   276    do_test io-2.7.6 {
   277      execsql { SELECT * FROM abc UNION ALL SELECT * FROM abc2 }
   278    } {1 2 3 4 5 6 7 8}
   279  }
   280  
   281  # Try an explicit ROLLBACK before the journal file is created.
   282  #
   283  do_test io-2.8.1 {
   284    execsql {
   285      BEGIN;
   286      DELETE FROM abc;
   287    }
   288    file exists test.db-journal
   289  } {0}
   290  do_test io-2.8.2 {
   291    execsql { SELECT * FROM abc }
   292  } {}
   293  do_test io-2.8.3 {
   294    execsql {
   295      ROLLBACK;
   296      SELECT * FROM abc;
   297    }
   298  } {1 2 3 4 5 6 7 8}
   299  
   300  # Test that the atomic write optimisation is not enabled if the sector
   301  # size is larger than the page-size.
   302  #
   303  do_test io-2.9.1 {
   304    db close
   305    sqlite3 db test.db
   306    sqlite3_simulate_device -char atomic -sectorsize 2048
   307    execsql {
   308      BEGIN;
   309      INSERT INTO abc VALUES(9, 10);
   310    }
   311    file exists test.db-journal
   312  } {1}
   313  do_test io-2.9.2 {
   314    execsql { ROLLBACK; }
   315    db close
   316    forcedelete test.db test.db-journal
   317    sqlite3 db test.db -vfs devsym
   318    execsql {
   319      PRAGMA auto_vacuum = OFF;
   320      PRAGMA page_size = 2048;
   321      CREATE TABLE abc(a, b);
   322    }
   323    execsql {
   324      BEGIN;
   325      INSERT INTO abc VALUES(9, 10);
   326    }
   327    file exists test.db-journal
   328  } {0}
   329  do_test io-2.9.3 {
   330    execsql { COMMIT }
   331  } {}
   332  
   333  # Test a couple of the more specific IOCAP_ATOMIC flags 
   334  # (i.e IOCAP_ATOMIC2K etc.).
   335  #
   336  do_test io-2.10.1 {
   337    sqlite3_simulate_device -char atomic1k
   338    execsql {
   339      BEGIN;
   340      INSERT INTO abc VALUES(11, 12);
   341    }
   342    file exists test.db-journal
   343  } {1}
   344  do_test io-2.10.2 {
   345    execsql { ROLLBACK }
   346    sqlite3_simulate_device -char atomic2k
   347    execsql {
   348      BEGIN;
   349      INSERT INTO abc VALUES(11, 12);
   350    }
   351    file exists test.db-journal
   352  } {0}
   353  do_test io-2.10.3 {
   354    execsql { ROLLBACK }
   355  } {}
   356  
   357  do_test io-2.11.0 {
   358    execsql { 
   359      PRAGMA locking_mode = exclusive;
   360      PRAGMA locking_mode;
   361    }
   362  } {exclusive exclusive}
   363  do_test io-2.11.1 {
   364    execsql { 
   365      INSERT INTO abc VALUES(11, 12);
   366    }
   367    file exists test.db-journal
   368  } {0}
   369  
   370  do_test io-2.11.2 {
   371    execsql { 
   372      PRAGMA locking_mode = normal;
   373      INSERT INTO abc VALUES(13, 14);
   374    }
   375    file exists test.db-journal
   376  } {0}
   377  
   378  } ;# /* ifcapable atomicwrite */
   379  
   380  #----------------------------------------------------------------------
   381  # Test cases io-3.* test the IOCAP_SEQUENTIAL optimization.
   382  #
   383  sqlite3_simulate_device -char sequential -sectorsize 0
   384  ifcapable pager_pragmas {
   385    do_test io-3.1 {
   386      db close
   387      forcedelete test.db test.db-journal
   388      sqlite3 db test.db -vfs devsym
   389      db eval {
   390        PRAGMA auto_vacuum=OFF;
   391      }
   392      # File size might be 1 due to the hack to work around ticket #3260.
   393      # Search for #3260 in os_unix.c for additional information.
   394      expr {[file size test.db]>1}
   395    } {0}
   396    do_test io-3.2 {
   397      execsql { CREATE TABLE abc(a, b) }
   398      nSync
   399      execsql {
   400        PRAGMA temp_store = memory;
   401        PRAGMA cache_size = 10;
   402        BEGIN;
   403        INSERT INTO abc VALUES('hello', 'world');
   404        INSERT INTO abc SELECT * FROM abc;
   405        INSERT INTO abc SELECT * FROM abc;
   406        INSERT INTO abc SELECT * FROM abc;
   407        INSERT INTO abc SELECT * FROM abc;
   408        INSERT INTO abc SELECT * FROM abc;
   409        INSERT INTO abc SELECT * FROM abc;
   410        INSERT INTO abc SELECT * FROM abc;
   411        INSERT INTO abc SELECT * FROM abc;
   412        INSERT INTO abc SELECT * FROM abc;
   413        INSERT INTO abc SELECT * FROM abc;
   414        INSERT INTO abc SELECT * FROM abc;
   415      }
   416      # File has grown - showing there was a cache-spill - but there 
   417      # have been no calls to fsync(). The file is probably about 30KB.
   418      # But some VFS implementations (symbian) buffer writes so the actual
   419      # size may be a little less than that. So this test case just tests
   420      # that the file is now greater than 20000 bytes in size.
   421      list [expr [file size test.db]>20000] [nSync]
   422    } {1 0}
   423    do_test io-3.3 {
   424      # The COMMIT requires a single fsync() - to the database file.
   425      execsql { COMMIT }
   426      list [file size test.db] [nSync]
   427    } "[expr {[nonzero_reserved_bytes]?40960:39936}] 1"
   428  }
   429  
   430  #----------------------------------------------------------------------
   431  # Test cases io-4.* test the IOCAP_SAFE_APPEND optimization.
   432  #
   433  sqlite3_simulate_device -char safe_append
   434  
   435  # With the SAFE_APPEND flag set, simple transactions require 3, rather
   436  # than 4, calls to fsync(). The fsync() calls are on:
   437  #
   438  #   1) The directory in which the journal file is created, (unix only)
   439  #   2) The journal file (to sync the page data),
   440  #   3) The database file.
   441  #
   442  # Normally, when the SAFE_APPEND flag is not set, there is another fsync()
   443  # on the journal file between steps (2) and (3) above.
   444  #
   445  set expected_sync_count 2
   446  if {$::tcl_platform(platform)=="unix"} {
   447    ifcapable dirsync {
   448      incr expected_sync_count
   449    }
   450  }
   451  
   452  do_test io-4.1 {
   453    execsql { DELETE FROM abc }
   454    nSync
   455    execsql { INSERT INTO abc VALUES('a', 'b') }
   456    nSync
   457  } $expected_sync_count
   458  
   459  # With SAFE_APPEND set, the nRec field of the journal file header should
   460  # be set to 0xFFFFFFFF before the first journal sync. The nRec field
   461  # occupies bytes 8-11 of the journal file.
   462  #
   463  do_test io-4.2.1 {
   464    execsql { BEGIN }
   465    execsql { INSERT INTO abc VALUES('c', 'd') }
   466    file exists test.db-journal
   467  } {1}
   468  if {$::tcl_platform(platform)=="unix"} {
   469    do_test io-4.2.2 {
   470      hexio_read test.db-journal 8 4
   471    } {FFFFFFFF}
   472  }
   473  do_test io-4.2.3 {
   474    execsql { COMMIT }
   475    nSync
   476  } $expected_sync_count
   477  sqlite3_simulate_device -char safe_append
   478  
   479  # With SAFE_APPEND set, there should only ever be one journal-header
   480  # written to the database, even though the sync-mode is "full".
   481  #
   482  do_test io-4.3.1 {
   483    execsql {
   484      INSERT INTO abc SELECT * FROM abc;
   485      INSERT INTO abc SELECT * FROM abc;
   486      INSERT INTO abc SELECT * FROM abc;
   487      INSERT INTO abc SELECT * FROM abc;
   488      INSERT INTO abc SELECT * FROM abc;
   489      INSERT INTO abc SELECT * FROM abc;
   490      INSERT INTO abc SELECT * FROM abc;
   491      INSERT INTO abc SELECT * FROM abc;
   492      INSERT INTO abc SELECT * FROM abc;
   493      INSERT INTO abc SELECT * FROM abc;
   494      INSERT INTO abc SELECT * FROM abc;
   495    }
   496    expr {[file size test.db]/1024}
   497  } {43}
   498  ifcapable pager_pragmas {
   499    do_test io-4.3.2 {
   500      execsql {
   501        PRAGMA synchronous = full;
   502        PRAGMA cache_size = 10;
   503        PRAGMA synchronous;
   504      }
   505    } {2}
   506  }
   507  do_test io-4.3.3 {
   508    execsql {
   509      BEGIN;
   510      UPDATE abc SET a = 'x';
   511    }
   512    file exists test.db-journal
   513  } {1}
   514  if {$tcl_platform(platform) != "symbian"} {
   515    # This test is not run on symbian because the file-buffer makes it
   516    # difficult to predict the exact size of the file as reported by 
   517    # [file size].
   518    do_test io-4.3.4 {
   519      # The UPDATE statement in the statement above modifies 41 pages 
   520      # (all pages in the database except page 1 and the root page of 
   521      # abc). Because the cache_size is set to 10, this must have required
   522      # at least 4 cache-spills. If there were no journal headers written
   523      # to the journal file after the cache-spill, then the size of the
   524      # journal file is give by:
   525      #
   526      #    <jrnl file size> = <jrnl header size> + nPage * (<page-size> + 8)
   527      #
   528      # If the journal file contains additional headers, this formula
   529      # will not predict the size of the journal file.
   530      #
   531      file size test.db-journal
   532    } [expr 512 + (1024+8)*41]
   533  }
   534  
   535  #----------------------------------------------------------------------
   536  # Test cases io-5.* test that the default page size is selected and
   537  # used correctly.
   538  #
   539  set tn 0
   540  foreach {char                 sectorsize pgsize} {
   541           {}                     512      1024
   542           {}                    1024      1024
   543           {}                    2048      2048
   544           {}                    8192      8192
   545           {}                   16384      8192
   546           {atomic}               512      8192
   547           {atomic512}            512      1024
   548           {atomic2K}             512      2048
   549           {atomic2K}            4096      4096
   550           {atomic2K atomic}      512      8192
   551           {atomic64K}            512      1024
   552  } {
   553    incr tn
   554    if {$pgsize>$::SQLITE_MAX_PAGE_SIZE} continue
   555    db close
   556    forcedelete test.db test.db-journal
   557    sqlite3_simulate_device -char $char -sectorsize $sectorsize
   558    sqlite3 db test.db -vfs devsym
   559    db eval {
   560      PRAGMA auto_vacuum=OFF;
   561    }
   562    ifcapable !atomicwrite {
   563      if {[regexp {^atomic} $char]} continue
   564    }
   565    do_test io-5.$tn {
   566      execsql {
   567        CREATE TABLE abc(a, b, c);
   568      }
   569      expr {[file size test.db]/2}
   570    } $pgsize
   571  }
   572  
   573  #----------------------------------------------------------------------
   574  #
   575  do_test io-6.1 {
   576    db close
   577    sqlite3_simulate_device -char atomic
   578    forcedelete test.db
   579    sqlite3 db test.db -vfs devsym
   580    execsql {
   581      PRAGMA mmap_size = 0;
   582      PRAGMA page_size = 1024;
   583      PRAGMA cache_size = 2000;
   584      CREATE TABLE t1(x);
   585      CREATE TABLE t2(x);
   586      CREATE TABLE t3(x);
   587      CREATE INDEX i3 ON t3(x);
   588      INSERT INTO t3 VALUES(randomblob(100));
   589      INSERT INTO t3 SELECT randomblob(100) FROM t3;
   590      INSERT INTO t3 SELECT randomblob(100) FROM t3;
   591      INSERT INTO t3 SELECT randomblob(100) FROM t3;
   592      INSERT INTO t3 SELECT randomblob(100) FROM t3;
   593      INSERT INTO t3 SELECT randomblob(100) FROM t3;
   594      INSERT INTO t3 SELECT randomblob(100) FROM t3;
   595      INSERT INTO t3 SELECT randomblob(100) FROM t3;
   596      INSERT INTO t3 SELECT randomblob(100) FROM t3;
   597      INSERT INTO t3 SELECT randomblob(100) FROM t3;
   598      INSERT INTO t3 SELECT randomblob(100) FROM t3;
   599      INSERT INTO t3 SELECT randomblob(100) FROM t3;
   600    }
   601  
   602    db_save_and_close
   603  } {}
   604  
   605  foreach {tn sql} {
   606    1 { BEGIN;
   607          INSERT INTO t1 VALUES('123');
   608          INSERT INTO t2 VALUES('456');
   609        COMMIT;
   610    }
   611    2 { BEGIN;
   612          INSERT INTO t1 VALUES('123');
   613        COMMIT;
   614    }
   615  } {
   616  
   617    # These tests don't work with memsubsys1, as it causes the effective page
   618    # cache size to become too small to hold the entire db in memory.
   619    if {[permutation] == "memsubsys1"} continue
   620  
   621    db_restore
   622    sqlite3 db test.db -vfs devsym
   623    execsql {
   624      PRAGMA cache_size = 2000;
   625      PRAGMA mmap_size = 0;
   626      SELECT x FROM t3 ORDER BY rowid;
   627      SELECT x FROM t3 ORDER BY x;
   628    }
   629    do_execsql_test 6.2.$tn.1 { PRAGMA integrity_check } {ok}
   630    do_execsql_test 6.2.$tn.2 $sql
   631  
   632    # Corrupt the database file on disk. This should not matter for the
   633    # purposes of the following "PRAGMA integrity_check", as the entire
   634    # database should be cached in the pager-cache. If corruption is
   635    # reported, it indicates that executing $sql caused the pager cache
   636    # to be flushed. Which is a bug.
   637    hexio_write test.db [expr 1024 * 5] [string repeat 00 2048]
   638    do_execsql_test 6.2.$tn.3 { PRAGMA integrity_check } {ok}
   639    db close
   640  }
   641  
   642  sqlite3_simulate_device -char {} -sectorsize 0
   643  finish_test