/ Check-in [228c5b16]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add coverage tests for pager.c.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 228c5b16af80c22e97d9d4deb351e0d3f4523f89
User & Date: dan 2010-08-12 11:25:48
Context
2010-08-12
16:36
If an error occurs in PagerSetPagesize(), set the output variable to the unmodified page-size before returning. check-in: 02def8f9 user: dan tags: trunk
11:25
Add coverage tests for pager.c. check-in: 228c5b16 user: dan tags: trunk
02:41
Increase the maximum page size from 32k to 64k. check-in: 45362437 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pager.c.

  4122   4122   
  4123   4123     /* Mark the page as clean. */
  4124   4124     if( rc==SQLITE_OK ){
  4125   4125       PAGERTRACE(("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno));
  4126   4126       sqlite3PcacheMakeClean(pPg);
  4127   4127     }
  4128   4128   
  4129         -  return pager_error(pPager, rc);
         4129  +  return pager_error(pPager, rc); 
  4130   4130   }
  4131   4131   
  4132   4132   
  4133   4133   /*
  4134   4134   ** Allocate and initialize a new Pager object and put a pointer to it
  4135   4135   ** in *ppPager. The pager should eventually be freed by passing it
  4136   4136   ** to sqlite3PagerClose().
................................................................................
  5697   5697         ** file. This can only happen in auto-vacuum mode.
  5698   5698         **
  5699   5699         ** Before reading the pages with page numbers larger than the 
  5700   5700         ** current value of Pager.dbSize, set dbSize back to the value
  5701   5701         ** that it took at the start of the transaction. Otherwise, the
  5702   5702         ** calls to sqlite3PagerGet() return zeroed pages instead of 
  5703   5703         ** reading data from the database file.
  5704         -      **
  5705         -      ** When journal_mode==OFF the dbOrigSize is always zero, so this
  5706         -      ** block never runs if journal_mode=OFF.
  5707   5704         */
  5708   5705     #ifndef SQLITE_OMIT_AUTOVACUUM
  5709   5706         if( pPager->dbSize<pPager->dbOrigSize 
  5710   5707          && pPager->journalMode!=PAGER_JOURNALMODE_OFF
  5711   5708         ){
  5712   5709           Pgno i;                                   /* Iterator variable */
  5713   5710           const Pgno iSkip = PAGER_MJ_PGNO(pPager); /* Pending lock page */
................................................................................
  6421   6418         */
  6422   6419         sqlite3OsClose(pPager->jfd);
  6423   6420         if( pPager->eLock>=RESERVED_LOCK ){
  6424   6421           sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
  6425   6422         }else{
  6426   6423           int rc = SQLITE_OK;
  6427   6424           int state = pPager->eState;
         6425  +        assert( state==PAGER_OPEN || state==PAGER_READER );
  6428   6426           if( state==PAGER_OPEN ){
  6429   6427             rc = sqlite3PagerSharedLock(pPager);
  6430   6428           }
  6431   6429           if( pPager->eState==PAGER_READER ){
  6432   6430             assert( rc==SQLITE_OK );
  6433   6431             rc = pagerLockDb(pPager, RESERVED_LOCK);
  6434   6432           }

Changes to src/vdbeaux.c.

  2057   2057   
  2058   2058       /* Check for one of the special errors */
  2059   2059       mrc = p->rc & 0xff;
  2060   2060       assert( p->rc!=SQLITE_IOERR_BLOCKED );  /* This error no longer exists */
  2061   2061       isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR
  2062   2062                        || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL;
  2063   2063       if( isSpecialError ){
  2064         -      /* If the query was read-only, we need do no rollback at all. Otherwise,
  2065         -      ** proceed with the special handling.
         2064  +      /* If the query was read-only and the error code is SQLITE_INTERRUPT, 
         2065  +      ** no rollback is necessary. Otherwise, at least a savepoint 
         2066  +      ** transaction must be rolled back to restore the database to a 
         2067  +      ** consistent state.
         2068  +      **
         2069  +      ** Even if the statement is read-only, it is important to perform
         2070  +      ** a statement or transaction rollback operation. If the error 
         2071  +      ** occured while writing to the journal, sub-journal or database
         2072  +      ** file as part of an effort to free up cache space (see function
         2073  +      ** pagerStress() in pager.c), the rollback is required to restore 
         2074  +      ** the pager to a consistent state.
  2066   2075         */
  2067   2076         if( !p->readOnly || mrc!=SQLITE_INTERRUPT ){
  2068   2077           if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) && p->usesStmtJournal ){
  2069   2078             eStatementOp = SAVEPOINT_ROLLBACK;
  2070   2079           }else{
  2071   2080             /* We are forced to roll back the active transaction. Before doing
  2072   2081             ** so, abort any other statements this handle currently has active.

Changes to test/lock_common.tcl.

    23     23       set tn 1
    24     24     } {
    25     25       proc code2 {tcl} { uplevel #0 $tcl }
    26     26       proc code3 {tcl} { uplevel #0 $tcl }
    27     27       set tn 2
    28     28     }] {
    29     29       faultsim_delete_and_reopen
           30  +
           31  +    proc code1 {tcl} { uplevel #0 $tcl }
    30     32     
    31     33       # Open connections [db2] and [db3]. Depending on which iteration this
    32     34       # is, the connections may be created in this interpreter, or in 
    33     35       # interpreters running in other OS processes. As such, the [db2] and [db3]
    34     36       # commands should only be accessed within [code2] and [code3] blocks,
    35     37       # respectively.
    36     38       #

Changes to test/pager1.test.

    11     11   #
    12     12   
    13     13   set testdir [file dirname $argv0]
    14     14   source $testdir/tester.tcl
    15     15   source $testdir/lock_common.tcl
    16     16   source $testdir/malloc_common.tcl
    17     17   source $testdir/wal_common.tcl
    18         - 
           18  +
    19     19   # Do not use a codec for tests in this file, as the database file is
    20     20   # manipulated directly using tcl scripts (using the [hexio_write] command).
    21     21   #
    22     22   do_not_use_codec
    23     23   
    24     24   #
    25     25   # pager1-1.*: Test inter-process locking (clients in multiple processes).
................................................................................
  2269   2269       csql1 { BEGIN; INSERT INTO t1 VALUES('c', 'd'); }
  2270   2270     } {1 {database is locked}}
  2271   2271     code2 { db2 close ; sqlite3 db2 test.db }
  2272   2272     do_test pager1-28.$tn.4 { 
  2273   2273       sql1 { INSERT INTO t1 VALUES('c', 'd'); COMMIT }
  2274   2274     } {}
  2275   2275   }
         2276  +
         2277  +#-------------------------------------------------------------------------
         2278  +# Normally, when changing from journal_mode=PERSIST to DELETE the pager
         2279  +# attempts to delete the journal file. However, if it cannot obtain a
         2280  +# RESERVED lock on the database file, this step is skipped.
         2281  +#
         2282  +do_multiclient_test tn {
         2283  +  do_test pager1-28.$tn.1 {
         2284  +    sql1 { 
         2285  +      PRAGMA journal_mode = PERSIST;
         2286  +      CREATE TABLE t1(a, b);
         2287  +      INSERT INTO t1 VALUES('a', 'b');
         2288  +    }
         2289  +  } {persist}
         2290  +  do_test pager1-28.$tn.2 { file exists test.db-journal } 1
         2291  +  do_test pager1-28.$tn.3 { sql1 { PRAGMA journal_mode = DELETE } } delete
         2292  +  do_test pager1-28.$tn.4 { file exists test.db-journal } 0
         2293  +
         2294  +  do_test pager1-28.$tn.5 {
         2295  +    sql1 { 
         2296  +      PRAGMA journal_mode = PERSIST;
         2297  +      INSERT INTO t1 VALUES('c', 'd');
         2298  +    }
         2299  +  } {persist}
         2300  +  do_test pager1-28.$tn.6 { file exists test.db-journal } 1
         2301  +  do_test pager1-28.$tn.7 {
         2302  +    sql2 { BEGIN; INSERT INTO t1 VALUES('e', 'f'); }
         2303  +  } {}
         2304  +  do_test pager1-28.$tn.8  { file exists test.db-journal } 1
         2305  +  do_test pager1-28.$tn.9  { sql1 { PRAGMA journal_mode = DELETE } } delete
         2306  +  do_test pager1-28.$tn.10 { file exists test.db-journal } 1
         2307  +
         2308  +  do_test pager1-28.$tn.11 { sql2 COMMIT } {}
         2309  +  do_test pager1-28.$tn.12 { file exists test.db-journal } 0
         2310  +
         2311  +  do_test pager1-28-$tn.13 {
         2312  +    code1 { set channel [db incrblob -readonly t1 a 2] }
         2313  +    sql1 {
         2314  +      PRAGMA journal_mode = PERSIST;
         2315  +      INSERT INTO t1 VALUES('g', 'h');
         2316  +    }
         2317  +  } {persist}
         2318  +  do_test pager1-28.$tn.14 { file exists test.db-journal } 1
         2319  +  do_test pager1-28.$tn.15 {
         2320  +    sql2 { BEGIN; INSERT INTO t1 VALUES('e', 'f'); }
         2321  +  } {}
         2322  +  do_test pager1-28.$tn.16 { sql1 { PRAGMA journal_mode = DELETE } } delete
         2323  +  do_test pager1-28.$tn.17 { file exists test.db-journal } 1
         2324  +
         2325  +  do_test pager1-28.$tn.17 { csql2 { COMMIT } } {1 {database is locked}}
         2326  +  do_test pager1-28-$tn.18 { code1 { read $channel } } c
         2327  +  do_test pager1-28-$tn.19 { code1 { close $channel } } {}
         2328  +  do_test pager1-28.$tn.20 { sql2 { COMMIT } } {}
         2329  +}
         2330  +
         2331  +
  2276   2332   finish_test

Changes to test/pager2.test.

   114    114     }
   115    115   }
   116    116   db close
   117    117   tv delete
   118    118   
   119    119   
   120    120   #-------------------------------------------------------------------------
   121         -# Test a ROLLBACK with journal_mode=off.
   122    121   #
   123         -breakpoint
          122  +# pager2-2.1: Test a ROLLBACK with journal_mode=off.
          123  +# pager2-2.2: Test shrinking the database (auto-vacuum) with 
          124  +#             journal_mode=off
          125  +#
   124    126   do_test pager2-2.1 {
   125    127     faultsim_delete_and_reopen
   126    128     execsql {
   127    129       CREATE TABLE t1(a, b);
   128    130       PRAGMA journal_mode = off;
   129    131       BEGIN;
   130    132         INSERT INTO t1 VALUES(1, 2);
   131    133       ROLLBACK;
   132    134       SELECT * FROM t1;
   133    135     }
   134    136   } {off 1 2}
          137  +do_test pager2-2.2 {
          138  +  faultsim_delete_and_reopen
          139  +  execsql {
          140  +    PRAGMA auto_vacuum = incremental;
          141  +    PRAGMA page_size = 1024;
          142  +    PRAGMA journal_mode = off;
          143  +    CREATE TABLE t1(a, b);
          144  +    INSERT INTO t1 VALUES(zeroblob(5000), zeroblob(5000));
          145  +    DELETE FROM t1;
          146  +    PRAGMA incremental_vacuum;
          147  +  }
          148  +  file size test.db
          149  +} {3072}
   135    150   
   136    151   finish_test

Changes to test/pagerfault.test.

    23     23   set a_string_counter 1
    24     24   proc a_string {n} {
    25     25     global a_string_counter
    26     26     incr a_string_counter
    27     27     string range [string repeat "${a_string_counter}." $n] 1 $n
    28     28   }
    29     29   db func a_string a_string
           30  +
           31  +if 1 {
    30     32   
    31     33   #-------------------------------------------------------------------------
    32     34   # Test fault-injection while rolling back a hot-journal file.
    33     35   #
    34     36   do_test pagerfault-1-pre1 {
    35     37     execsql {
    36     38       PRAGMA journal_mode = DELETE;
................................................................................
  1113   1115   do_faultsim_test pagerfault-24 -prep {
  1114   1116     faultsim_delete_and_reopen
  1115   1117     db eval { PRAGMA temp_store = file }
  1116   1118     execsql { CREATE TABLE x(a, b) }
  1117   1119   } -body {
  1118   1120     execsql { CREATE TEMP TABLE t1(a, b) }
  1119   1121   } -test {
  1120         -  faultsim_test_result {0 {}} {1 {unable to open a temporary database file for storing temporary tables}}
         1122  +  faultsim_test_result {0 {}} \
         1123  +    {1 {unable to open a temporary database file for storing temporary tables}}
  1121   1124     set ic [db eval { PRAGMA temp.integrity_check }]
  1122   1125     if {$ic != "ok"} { error "Integrity check: $ic" }
  1123   1126   }
  1124   1127   
         1128  +}
         1129  +
         1130  +proc lockrows {n} {
         1131  +  if {$n==0} { return "" }
         1132  +  db eval { SELECT * FROM t1 WHERE oid = $n } { 
         1133  +    return [lockrows [expr {$n-1}]]
         1134  +  }
         1135  +}
         1136  +
         1137  +do_test pagerfault-25-pre1 {
         1138  +  faultsim_delete_and_reopen
         1139  +  db func a_string a_string
         1140  +  execsql {
         1141  +    PRAGMA page_size = 1024;
         1142  +    PRAGMA auto_vacuum = 0;
         1143  +    CREATE TABLE t1(a);
         1144  +    INSERT INTO t1 VALUES(a_string(500));
         1145  +    INSERT INTO t1 SELECT a_string(500) FROM t1;
         1146  +    INSERT INTO t1 SELECT a_string(500) FROM t1;
         1147  +    INSERT INTO t1 SELECT a_string(500) FROM t1;
         1148  +    INSERT INTO t1 SELECT a_string(500) FROM t1;
         1149  +    INSERT INTO t1 SELECT a_string(500) FROM t1;
         1150  +  }
         1151  +  faultsim_save_and_close
         1152  +} {}
         1153  +do_faultsim_test pagerfault-25 -faults full -prep {
         1154  +  faultsim_restore_and_reopen
         1155  +  db func a_string a_string
         1156  +  set ::channel [db incrblob -readonly t1 a 1]
         1157  +  execsql { 
         1158  +    PRAGMA cache_size = 10;
         1159  +    BEGIN;
         1160  +      INSERT INTO t1 VALUES(a_string(3000));
         1161  +      INSERT INTO t1 VALUES(a_string(3000));
         1162  +  }
         1163  +} -body {
         1164  +  lockrows 30
         1165  +} -test {
         1166  +  catch { lockrows 30 }
         1167  +  close $::channel
         1168  +  faultsim_test_result {0 {}} 
         1169  +}
  1125   1170   
  1126   1171   
  1127   1172   finish_test