gitlab.com/CoiaPrant/sqlite3@v1.19.1/testdata/tcl/wal.test (about)

     1  # 2010 April 13
     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 operation of the library in
    13  # "PRAGMA journal_mode=WAL" mode.
    14  #
    15  
    16  set testdir [file dirname $argv0]
    17  source $testdir/tester.tcl
    18  source $testdir/lock_common.tcl
    19  source $testdir/malloc_common.tcl
    20  source $testdir/wal_common.tcl
    21  
    22  set testprefix wal
    23  
    24  ifcapable !wal {finish_test ; return }
    25  test_set_config_pagecache 0 0
    26  
    27  proc reopen_db {} {
    28    catch { db close }
    29    forcedelete test.db test.db-wal test.db-wal-summary
    30    sqlite3_wal db test.db
    31  }
    32  
    33  set ::blobcnt 0
    34  proc blob {nByte} {
    35    incr ::blobcnt
    36    return [string range [string repeat "${::blobcnt}x" $nByte] 1 $nByte]
    37  }
    38  
    39  proc sqlite3_wal {args} {
    40    eval sqlite3 $args
    41    [lindex $args 0] eval { PRAGMA auto_vacuum = 0 }
    42    [lindex $args 0] eval { PRAGMA page_size = 1024 }
    43    [lindex $args 0] eval { PRAGMA journal_mode = wal }
    44    [lindex $args 0] eval { PRAGMA synchronous = normal }
    45    [lindex $args 0] function blob blob
    46    db timeout 1000
    47  }
    48  
    49  proc log_deleted {logfile} {
    50    return [expr [file exists $logfile]==0]
    51  }
    52  
    53  #
    54  # These are 'warm-body' tests used while developing the WAL code. They
    55  # serve to prove that a few really simple cases work:
    56  #
    57  # wal-1.*: Read and write the database.
    58  # wal-2.*: Test MVCC with one reader, one writer.
    59  # wal-3.*: Test transaction rollback.
    60  # wal-4.*: Test savepoint/statement rollback.
    61  # wal-5.*: Test the temp database.
    62  # wal-6.*: Test creating databases with different page sizes.
    63  #
    64  #
    65  #
    66  do_test wal-0.1 {
    67    execsql { PRAGMA auto_vacuum = 0 }
    68    execsql { PRAGMA synchronous = normal }
    69    execsql { PRAGMA journal_mode = wal }
    70  } {wal}
    71  do_test wal-0.2 {
    72    file size test.db
    73  } {1024}
    74  
    75  do_test wal-1.0 {
    76    execsql { 
    77      BEGIN;
    78      CREATE TABLE t1(a, b); 
    79    }
    80    list [file exists test.db-journal] \
    81         [file exists test.db-wal]     \
    82         [file size test.db]
    83  } {0 1 1024}
    84  do_test wal-1.1 {
    85    execsql COMMIT
    86    list [file exists test.db-journal] [file exists test.db-wal]
    87  } {0 1}
    88  do_test wal-1.2 {
    89    # There are now two pages in the log.
    90    file size test.db-wal
    91  } [wal_file_size 2 1024]
    92  
    93  do_test wal-1.3 {
    94    execsql { SELECT * FROM sqlite_master }
    95  } {table t1 t1 2 {CREATE TABLE t1(a, b)}}
    96  
    97  do_test wal-1.4 {
    98    execsql { INSERT INTO t1 VALUES(1, 2) }
    99    execsql { INSERT INTO t1 VALUES(3, 4) }
   100    execsql { INSERT INTO t1 VALUES(5, 6) }
   101    execsql { INSERT INTO t1 VALUES(7, 8) }
   102    execsql { INSERT INTO t1 VALUES(9, 10) }
   103  } {}
   104  
   105  do_test wal-1.5 {
   106    execsql { SELECT * FROM t1 }
   107  } {1 2 3 4 5 6 7 8 9 10}
   108  
   109  do_test wal-2.1 {
   110    sqlite3_wal db2 ./test.db
   111    execsql { BEGIN; SELECT * FROM t1 } db2
   112  } {1 2 3 4 5 6 7 8 9 10}
   113  
   114  do_test wal-2.2 {
   115    execsql { INSERT INTO t1 VALUES(11, 12) }
   116    execsql { SELECT * FROM t1 }
   117  } {1 2 3 4 5 6 7 8 9 10 11 12}
   118  
   119  do_test wal-2.3 {
   120    execsql { SELECT * FROM t1 } db2
   121  } {1 2 3 4 5 6 7 8 9 10}
   122  
   123  do_test wal-2.4 {
   124    execsql { INSERT INTO t1 VALUES(13, 14) }
   125    execsql { SELECT * FROM t1 }
   126  } {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
   127  
   128  do_test wal-2.5 {
   129    execsql { SELECT * FROM t1 } db2
   130  } {1 2 3 4 5 6 7 8 9 10}
   131  
   132  do_test wal-2.6 {
   133    execsql { COMMIT; SELECT * FROM t1 } db2
   134  } {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
   135  
   136  do_test wal-3.1 {
   137    execsql { BEGIN; DELETE FROM t1 }
   138    execsql { SELECT * FROM t1 }
   139  } {}
   140  do_test wal-3.2 {
   141    execsql { SELECT * FROM t1 } db2
   142  } {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
   143  do_test wal-3.3 {
   144    execsql { ROLLBACK }
   145    execsql { SELECT * FROM t1 }
   146  } {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
   147  db2 close
   148  
   149  #-------------------------------------------------------------------------
   150  # The following tests, wal-4.*, test that savepoints work with WAL 
   151  # databases.
   152  #
   153  do_test wal-4.1 {
   154    execsql {
   155      DELETE FROM t1;
   156      BEGIN;
   157        INSERT INTO t1 VALUES('a', 'b');
   158        SAVEPOINT sp;
   159          INSERT INTO t1 VALUES('c', 'd');
   160          SELECT * FROM t1;
   161    }
   162  } {a b c d}
   163  do_test wal-4.2 {
   164    execsql {
   165        ROLLBACK TO sp;
   166        SELECT * FROM t1;
   167    }
   168  } {a b}
   169  do_test wal-4.3 {
   170    execsql {
   171      COMMIT;
   172      SELECT * FROM t1;
   173    }
   174  } {a b}
   175  
   176  do_test wal-4.4.1 {
   177    db close
   178    sqlite3 db test.db
   179    db func blob blob
   180    list [execsql { SELECT * FROM t1 }] [file size test.db-wal]
   181  } {{a b} 0}
   182  do_test wal-4.4.2 {
   183    execsql { PRAGMA cache_size = 10 }
   184    execsql {
   185      CREATE TABLE t2(a, b);
   186      INSERT INTO t2 VALUES(blob(400), blob(400));
   187      SAVEPOINT tr;
   188        INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /*  2 */
   189        INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /*  4 */
   190        INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /*  8 */
   191        INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /* 16 */
   192        INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /* 32 */
   193        INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /*  2 */
   194        INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /*  4 */
   195        INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /*  8 */
   196        INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /* 16 */
   197        INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /* 32 */
   198        SELECT count(*) FROM t2;
   199    }
   200  } {32}
   201  do_test wal-4.4.3 {
   202    execsql { ROLLBACK TO tr }
   203  } {}
   204  do_test wal-4.4.4 {
   205    set logsize [file size test.db-wal]
   206    execsql {
   207        INSERT INTO t1 VALUES('x', 'y');
   208      RELEASE tr;
   209    }
   210    expr { $logsize == [file size test.db-wal] }
   211  } {1}
   212  do_test wal-4.4.5 {
   213    execsql { SELECT count(*) FROM t2 }
   214  } {1}
   215  do_test wal-4.4.6 {
   216    forcecopy test.db test2.db
   217    forcecopy test.db-wal test2.db-wal
   218    sqlite3 db2 test2.db
   219    execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 } db2
   220  } {1 2}
   221  do_test wal-4.4.7 {
   222    execsql { PRAGMA integrity_check } db2
   223  } {ok}
   224  db2 close
   225  
   226  do_test wal-4.5.1 {
   227    reopen_db
   228    db func blob blob
   229    execsql {
   230      PRAGMA journal_mode = WAL;
   231      CREATE TABLE t1(a, b);
   232      INSERT INTO t1 VALUES('a', 'b');
   233    }
   234    sqlite3 db test.db
   235    db func blob blob
   236    list [execsql { SELECT * FROM t1 }] [file size test.db-wal]
   237  } {{a b} 0}
   238  do_test wal-4.5.2 {
   239    execsql { PRAGMA cache_size = 10 }
   240    execsql {
   241      CREATE TABLE t2(a, b);
   242      BEGIN;
   243      INSERT INTO t2 VALUES(blob(400), blob(400));
   244      SAVEPOINT tr;
   245        INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /*  2 */
   246        INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /*  4 */
   247        INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /*  8 */
   248        INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /* 16 */
   249        INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /* 32 */
   250        INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /*  2 */
   251        INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /*  4 */
   252        INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /*  8 */
   253        INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /* 16 */
   254        INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /* 32 */
   255        SELECT count(*) FROM t2;
   256    }
   257  } {32}
   258  do_test wal-4.5.3 {
   259    execsql { ROLLBACK TO tr }
   260  } {}
   261  do_test wal-4.5.4 {
   262    set logsize [file size test.db-wal]
   263    execsql {
   264        INSERT INTO t1 VALUES('x', 'y');
   265      RELEASE tr;
   266      COMMIT;
   267    }
   268    expr { $logsize == [file size test.db-wal] }
   269  } {1}
   270  do_test wal-4.5.5 {
   271    execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 }
   272  } {1 2}
   273  do_test wal-4.5.6 {
   274    forcecopy test.db test2.db
   275    forcecopy test.db-wal test2.db-wal
   276    sqlite3 db2 test2.db
   277    execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 } db2
   278  } {1 2}
   279  do_test wal-4.5.7 {
   280    execsql { PRAGMA integrity_check } db2
   281  } {ok}
   282  db2 close
   283  
   284  do_test wal-4.6.1 {
   285    execsql {
   286      DELETE FROM t2;
   287      PRAGMA wal_checkpoint;
   288      BEGIN;
   289        INSERT INTO t2 VALUES('w', 'x');
   290        SAVEPOINT save;
   291          INSERT INTO t2 VALUES('y', 'z');
   292        ROLLBACK TO save;
   293      COMMIT;
   294    }
   295    execsql { SELECT * FROM t2 }
   296  } {w x}
   297  
   298  
   299  reopen_db
   300  do_test wal-5.1 {
   301    execsql {
   302      CREATE TEMP TABLE t2(a, b);
   303      INSERT INTO t2 VALUES(1, 2);
   304    }
   305  } {}
   306  do_test wal-5.2 {
   307    execsql {
   308      BEGIN;
   309        INSERT INTO t2 VALUES(3, 4);
   310        SELECT * FROM t2;
   311    }
   312  } {1 2 3 4}
   313  do_test wal-5.3 {
   314    execsql {
   315      ROLLBACK;
   316      SELECT * FROM t2;
   317    }
   318  } {1 2}
   319  do_test wal-5.4 {
   320    execsql {
   321      CREATE TEMP TABLE t3(x UNIQUE);
   322      BEGIN;
   323        INSERT INTO t2 VALUES(3, 4);
   324        INSERT INTO t3 VALUES('abc');
   325    }
   326    catchsql { INSERT INTO t3 VALUES('abc') }
   327  } {1 {UNIQUE constraint failed: t3.x}}
   328  do_test wal-5.5 {
   329    execsql {
   330      COMMIT;
   331      SELECT * FROM t2;
   332    }
   333  } {1 2 3 4}
   334  db close
   335  
   336  foreach sector {512 4096} {
   337    sqlite3_simulate_device -sectorsize $sector
   338    foreach pgsz {512 1024 2048 4096} {
   339      forcedelete test.db test.db-wal
   340      do_test wal-6.$sector.$pgsz.1 {
   341        sqlite3 db test.db -vfs devsym
   342        execsql "
   343          PRAGMA page_size = $pgsz;
   344          PRAGMA auto_vacuum = 0;
   345          PRAGMA journal_mode = wal;
   346        "
   347        execsql "
   348          CREATE TABLE t1(a, b);
   349          INSERT INTO t1 VALUES(1, 2);
   350        "
   351        db close
   352        file size test.db
   353      } [expr $pgsz*2]
   354    
   355      do_test wal-6.$sector.$pgsz.2 {
   356        log_deleted test.db-wal
   357      } {1}
   358    }
   359  }
   360  
   361  do_test wal-7.1 {
   362    forcedelete test.db test.db-wal
   363    sqlite3_wal db test.db
   364    execsql {
   365      PRAGMA page_size = 1024;
   366      CREATE TABLE t1(a, b);
   367      INSERT INTO t1 VALUES(1, 2);
   368    }
   369    list [file size test.db] [file size test.db-wal]
   370  } [list 1024 [wal_file_size 3 1024]]
   371  do_test wal-7.2 {
   372    execsql { PRAGMA wal_checkpoint }
   373    list [file size test.db] [file size test.db-wal]
   374  } [list 2048 [wal_file_size 3 1024]]
   375  
   376  # Execute some transactions in auto-vacuum mode to test database file
   377  # truncation.
   378  #
   379  do_test wal-8.1 {
   380    reopen_db
   381    catch { db close }
   382    forcedelete test.db test.db-wal
   383  
   384    sqlite3 db test.db
   385    db function blob blob
   386    execsql {
   387      PRAGMA auto_vacuum = 1;
   388      PRAGMA journal_mode = wal;
   389      PRAGMA auto_vacuum;
   390    }
   391  } {wal 1}
   392  do_test wal-8.2 {
   393    execsql {
   394      PRAGMA page_size = 1024;
   395      CREATE TABLE t1(x);
   396      INSERT INTO t1 VALUES(blob(900));
   397      INSERT INTO t1 VALUES(blob(900));
   398      INSERT INTO t1 SELECT blob(900) FROM t1;       /*  4 */
   399      INSERT INTO t1 SELECT blob(900) FROM t1;       /*  8 */
   400      INSERT INTO t1 SELECT blob(900) FROM t1;       /* 16 */
   401      INSERT INTO t1 SELECT blob(900) FROM t1;       /* 32 */
   402      INSERT INTO t1 SELECT blob(900) FROM t1;       /* 64 */
   403      PRAGMA wal_checkpoint;
   404    }
   405    file size test.db
   406  } [expr 68*1024]
   407  do_test wal-8.3 {
   408    execsql { 
   409      DELETE FROM t1 WHERE rowid<54;
   410      PRAGMA wal_checkpoint;
   411    }
   412    file size test.db
   413  } [expr 14*1024]
   414  
   415  # Run some "warm-body" tests to ensure that log-summary files with more
   416  # than 256 entries (log summaries that contain index blocks) work Ok.
   417  #
   418  do_test wal-9.1 {
   419    reopen_db
   420    execsql {
   421      PRAGMA cache_size=2000;
   422      CREATE TABLE t1(x PRIMARY KEY);
   423      INSERT INTO t1 VALUES(blob(900));
   424      INSERT INTO t1 VALUES(blob(900));
   425      INSERT INTO t1 SELECT blob(900) FROM t1;       /*  4 */
   426      INSERT INTO t1 SELECT blob(900) FROM t1;       /*  8 */
   427      INSERT INTO t1 SELECT blob(900) FROM t1;       /* 16 */
   428      INSERT INTO t1 SELECT blob(900) FROM t1;       /* 32 */
   429      INSERT INTO t1 SELECT blob(900) FROM t1;       /* 64 */
   430      INSERT INTO t1 SELECT blob(900) FROM t1;       /* 128 */
   431      INSERT INTO t1 SELECT blob(900) FROM t1;       /* 256 */
   432    }
   433    file size test.db
   434  } 1024
   435  do_test wal-9.2 {
   436    sqlite3_wal db2 test.db
   437    execsql {PRAGMA integrity_check } db2
   438  } {ok}
   439  
   440  do_test wal-9.3 {
   441    forcedelete test2.db test2.db-wal
   442    copy_file test.db test2.db
   443    copy_file test.db-wal test2.db-wal
   444    sqlite3_wal db3 test2.db 
   445    execsql {PRAGMA integrity_check } db3
   446  } {ok}
   447  db3 close
   448  
   449  do_test wal-9.4 {
   450    execsql { PRAGMA wal_checkpoint }
   451    db2 close
   452    sqlite3_wal db2 test.db
   453    execsql {PRAGMA integrity_check } db2
   454  } {ok}
   455  
   456  foreach handle {db db2 db3} { catch { $handle close } }
   457  unset handle
   458  
   459  #-------------------------------------------------------------------------
   460  # The following block of tests - wal-10.* - test that the WAL locking 
   461  # scheme works in simple cases. This block of tests is run twice. Once
   462  # using multiple connections in the address space of the current process,
   463  # and once with all connections except one running in external processes.
   464  #
   465  do_multiclient_test tn {
   466  
   467    # Initialize the database schema and contents.
   468    #
   469    do_test wal-10.$tn.1 {
   470      execsql {
   471        PRAGMA auto_vacuum = 0;
   472        PRAGMA journal_mode = wal;
   473        CREATE TABLE t1(a, b);
   474        INSERT INTO t1 VALUES(1, 2);
   475        SELECT * FROM t1;
   476      }
   477    } {wal 1 2}
   478  
   479    # Open a transaction and write to the database using [db]. Check that [db2]
   480    # is still able to read the snapshot before the transaction was opened.
   481    #
   482    do_test wal-10.$tn.2 {
   483      execsql { BEGIN; INSERT INTO t1 VALUES(3, 4); }
   484      sql2 {SELECT * FROM t1}
   485    } {1 2}
   486  
   487    # Have [db] commit the transaction. Check that [db2] is now seeing the 
   488    # new, updated snapshot.
   489    #
   490    do_test wal-10.$tn.3 {
   491      execsql { COMMIT }
   492      sql2 {SELECT * FROM t1}
   493    } {1 2 3 4}
   494  
   495    # Have [db2] open a read transaction. Then write to the db via [db]. Check
   496    # that [db2] is still seeing the original snapshot. Then read with [db3].
   497    # [db3] should see the newly committed data.
   498    #
   499    do_test wal-10.$tn.4 {
   500      sql2 { BEGIN ; SELECT * FROM t1}
   501    } {1 2 3 4}
   502    do_test wal-10.$tn.5 {
   503      execsql { INSERT INTO t1 VALUES(5, 6); }
   504      sql2 {SELECT * FROM t1}
   505    } {1 2 3 4}
   506    do_test wal-10.$tn.6 {
   507      sql3 {SELECT * FROM t1}
   508    } {1 2 3 4 5 6}
   509    do_test wal-10.$tn.7 {
   510      sql2 COMMIT
   511    } {}
   512  
   513    # Have [db2] open a write transaction. Then attempt to write to the 
   514    # database via [db]. This should fail (writer lock cannot be obtained).
   515    #
   516    # Then open a read-transaction with [db]. Commit the [db2] transaction
   517    # to disk. Verify that [db] still cannot write to the database (because
   518    # it is reading an old snapshot).
   519    #
   520    # Close the current [db] transaction. Open a new one. [db] can now write
   521    # to the database (as it is not locked and [db] is reading the latest
   522    # snapshot).
   523    #
   524    do_test wal-10.$tn.7 {
   525      sql2 { BEGIN; INSERT INTO t1 VALUES(7, 8) ; }
   526      catchsql { INSERT INTO t1 VALUES(9, 10) }
   527    } {1 {database is locked}}
   528    do_test wal-10.$tn.8 {
   529      execsql { BEGIN ; SELECT * FROM t1 }
   530    } {1 2 3 4 5 6}
   531    do_test wal-10.$tn.9 {
   532      sql2 COMMIT
   533      catchsql { INSERT INTO t1 VALUES(9, 10) }
   534    } {1 {database is locked}}
   535    do_test wal-10.$tn.10 {
   536      execsql { COMMIT }
   537      execsql { BEGIN }
   538      execsql { INSERT INTO t1 VALUES(9, 10) }
   539      execsql { COMMIT }
   540      execsql { SELECT * FROM t1 }
   541    } {1 2 3 4 5 6 7 8 9 10}
   542  
   543    # Open a read transaction with [db2]. Check that this prevents [db] from
   544    # checkpointing the database. But not from writing to it.
   545    #
   546    do_test wal-10.$tn.11 {
   547      sql2 { BEGIN; SELECT * FROM t1 }
   548    } {1 2 3 4 5 6 7 8 9 10}
   549    do_test wal-10.$tn.12 {
   550      catchsql { PRAGMA wal_checkpoint } 
   551    } {0 {0 7 7}}   ;# Reader no longer block checkpoints
   552    do_test wal-10.$tn.13 {
   553      execsql { INSERT INTO t1 VALUES(11, 12) }
   554      sql2 {SELECT * FROM t1}
   555    } {1 2 3 4 5 6 7 8 9 10}
   556  
   557    # Writers do not block checkpoints any more either.
   558    #
   559    do_test wal-10.$tn.14 {
   560      catchsql { PRAGMA wal_checkpoint } 
   561    } {0 {0 8 7}}
   562  
   563    # The following series of test cases used to verify another blocking
   564    # case in WAL - a case which no longer blocks.
   565    #
   566    do_test wal-10.$tn.15 {
   567      sql2 { COMMIT; BEGIN; SELECT * FROM t1; }
   568    } {1 2 3 4 5 6 7 8 9 10 11 12}
   569    do_test wal-10.$tn.16 {
   570      catchsql { PRAGMA wal_checkpoint } 
   571    } {0 {0 8 8}}
   572    do_test wal-10.$tn.17 {
   573      execsql { PRAGMA wal_checkpoint } 
   574    } {0 8 8}
   575    do_test wal-10.$tn.18 {
   576      sql3 { BEGIN; SELECT * FROM t1 }
   577    } {1 2 3 4 5 6 7 8 9 10 11 12}
   578    do_test wal-10.$tn.19 {
   579      catchsql { INSERT INTO t1 VALUES(13, 14) }
   580    } {0 {}}
   581    do_test wal-10.$tn.20 {
   582      execsql { SELECT * FROM t1 }
   583    } {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
   584    do_test wal-10.$tn.21 {
   585      sql3 COMMIT
   586      sql2 COMMIT
   587    } {}
   588    do_test wal-10.$tn.22 {
   589      execsql { SELECT * FROM t1 }
   590    } {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
   591  
   592    # Another series of tests that used to demonstrate blocking behavior
   593    # but which now work.
   594    #
   595    do_test wal-10.$tn.23 {
   596      execsql { PRAGMA wal_checkpoint }
   597    } {0 9 9}
   598    do_test wal-10.$tn.24 {
   599      sql2 { BEGIN; SELECT * FROM t1; }
   600    } {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
   601    do_test wal-10.$tn.25 {
   602      execsql { PRAGMA wal_checkpoint }
   603    } {0 9 9}
   604    do_test wal-10.$tn.26 {
   605      catchsql { INSERT INTO t1 VALUES(15, 16) }
   606    } {0 {}}
   607    do_test wal-10.$tn.27 {
   608      sql3 { INSERT INTO t1 VALUES(17, 18) }
   609    } {}
   610    do_test wal-10.$tn.28 {
   611      code3 {
   612        set ::STMT [sqlite3_prepare db3 "SELECT * FROM t1" -1 TAIL]
   613        sqlite3_step $::STMT
   614      }
   615      execsql { SELECT * FROM t1 }
   616    } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18}
   617    do_test wal-10.$tn.29 {
   618      execsql { INSERT INTO t1 VALUES(19, 20) }
   619      catchsql { PRAGMA wal_checkpoint }
   620    } {0 {0 3 0}}
   621    do_test wal-10.$tn.30 {
   622      code3 { sqlite3_finalize $::STMT }
   623      execsql { PRAGMA wal_checkpoint }
   624    } {0 3 0}
   625  
   626    # At one point, if a reader failed to upgrade to a writer because it
   627    # was reading an old snapshot, the write-locks were not being released.
   628    # Test that this bug has been fixed.
   629    #
   630    do_test wal-10.$tn.31 {
   631      sql2 COMMIT
   632      execsql { BEGIN ; SELECT * FROM t1 }
   633      sql2 { INSERT INTO t1 VALUES(21, 22) }
   634      catchsql { INSERT INTO t1 VALUES(23, 24) }
   635    } {1 {database is locked}}
   636    do_test wal-10.$tn.32 {
   637      # This statement would fail when the bug was present.
   638      sql2 { INSERT INTO t1 VALUES(23, 24) }
   639    } {}
   640    do_test wal-10.$tn.33 {
   641      execsql { SELECT * FROM t1 ; COMMIT }
   642    } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20}
   643    do_test wal-10.$tn.34 {
   644      execsql { SELECT * FROM t1 }
   645    } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24}
   646  
   647    # Test that if a checkpointer cannot obtain the required locks, it
   648    # releases all locks before returning a busy error.
   649    #
   650    do_test wal-10.$tn.35 {
   651      execsql { 
   652        DELETE FROM t1;
   653        INSERT INTO t1 VALUES('a', 'b');
   654        INSERT INTO t1 VALUES('c', 'd');
   655      }
   656      sql2 {
   657        BEGIN;
   658          SELECT * FROM t1;
   659      }
   660    } {a b c d}
   661    do_test wal-10.$tn.36 {
   662      catchsql { PRAGMA wal_checkpoint }
   663    } {0 {0 8 8}}
   664    do_test wal-10.$tn.36 {
   665      sql3 { INSERT INTO t1 VALUES('e', 'f') }
   666      sql2 { SELECT * FROM t1 }
   667    } {a b c d}
   668    do_test wal-10.$tn.37 {
   669      sql2 COMMIT
   670      execsql { PRAGMA wal_checkpoint }
   671    } {0 9 9}
   672  }
   673  
   674  #-------------------------------------------------------------------------
   675  # This block of tests, wal-11.*, test that nothing goes terribly wrong
   676  # if frames must be written to the log file before a transaction is
   677  # committed (in order to free up memory).
   678  #
   679  do_test wal-11.1 {
   680    reopen_db
   681    execsql {
   682      PRAGMA cache_size = 10;
   683      PRAGMA page_size = 1024;
   684      CREATE TABLE t1(x PRIMARY KEY);
   685    }
   686    list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044]
   687  } {1 3}
   688  do_test wal-11.2 {
   689    execsql { PRAGMA wal_checkpoint }
   690    list [expr [file size test.db]/1024] [file size test.db-wal]
   691  } [list 3 [wal_file_size 3 1024]]
   692  do_test wal-11.3 {
   693    execsql { INSERT INTO t1 VALUES( blob(900) ) }
   694    list [expr [file size test.db]/1024] [file size test.db-wal]
   695  } [list 3 [wal_file_size 4 1024]]
   696  
   697  do_test wal-11.4 {
   698    execsql { 
   699      BEGIN;
   700        INSERT INTO t1 SELECT blob(900) FROM t1;   -- 2
   701        INSERT INTO t1 SELECT blob(900) FROM t1;   -- 4
   702        INSERT INTO t1 SELECT blob(900) FROM t1;   -- 8
   703        INSERT INTO t1 SELECT blob(900) FROM t1;   -- 16
   704    }
   705    list [expr [file size test.db]/1024] [file size test.db-wal]
   706  } [list 3 [wal_file_size 32 1024]]
   707  do_test wal-11.5 {
   708    execsql { 
   709      SELECT count(*) FROM t1;
   710      PRAGMA integrity_check;
   711    }
   712  } {16 ok}
   713  do_test wal-11.6 {
   714    execsql COMMIT
   715    list [expr [file size test.db]/1024] [file size test.db-wal]
   716  } [list 3 [wal_file_size 40 1024]]
   717  do_test wal-11.7 {
   718    execsql { 
   719      SELECT count(*) FROM t1;
   720      PRAGMA integrity_check;
   721    }
   722  } {16 ok}
   723  do_test wal-11.8 {
   724    execsql { PRAGMA wal_checkpoint }
   725    list [expr [file size test.db]/1024] [file size test.db-wal]
   726  } [list 37 [wal_file_size 40 1024]]
   727  do_test wal-11.9 {
   728    db close
   729    list [expr [file size test.db]/1024] [log_deleted test.db-wal]
   730  } {37 1}
   731  sqlite3_wal db test.db
   732  
   733  # After adding the capability of WAL to overwrite prior uncommitted
   734  # frame in the WAL-file with revised content, the size of the WAL file
   735  # following cache-spill is smaller.
   736  #
   737  #set nWal 39
   738  #if {[permutation]!="mmap"} {set nWal 37}
   739  #ifcapable !mmap {set nWal 37}
   740  set nWal 34
   741  
   742  do_test wal-11.10 {
   743    execsql {
   744      PRAGMA cache_size = 10;
   745      BEGIN;
   746        INSERT INTO t1 SELECT blob(900) FROM t1;   -- 32
   747        SELECT count(*) FROM t1;
   748    }
   749    list [expr [file size test.db]/1024] [file size test.db-wal]
   750  } [list 37 [wal_file_size $nWal 1024]]
   751  do_test wal-11.11 {
   752    execsql {
   753        SELECT count(*) FROM t1;
   754      ROLLBACK;
   755      SELECT count(*) FROM t1;
   756    }
   757  } {32 16}
   758  do_test wal-11.12 {
   759    list [expr [file size test.db]/1024] [file size test.db-wal]
   760  } [list 37 [wal_file_size $nWal 1024]]
   761  do_test wal-11.13 {
   762    execsql {
   763      INSERT INTO t1 VALUES( blob(900) );
   764      SELECT count(*) FROM t1;
   765      PRAGMA integrity_check;
   766    }
   767  } {17 ok}
   768  do_test wal-11.14 {
   769    list [expr [file size test.db]/1024] [file size test.db-wal]
   770  } [list 37 [wal_file_size $nWal 1024]]
   771  
   772  
   773  #-------------------------------------------------------------------------
   774  # This block of tests, wal-12.*, tests the fix for a problem that 
   775  # could occur if a log that is a prefix of an older log is written 
   776  # into a reused log file.
   777  #
   778  reopen_db
   779  do_test wal-12.1 {
   780    execsql {
   781      PRAGMA page_size = 1024;
   782      CREATE TABLE t1(x, y);
   783      CREATE TABLE t2(x, y);
   784      INSERT INTO t1 VALUES('A', 1);
   785    }
   786    list [expr [file size test.db]/1024] [file size test.db-wal]
   787  } [list 1 [wal_file_size 5 1024]]
   788  do_test wal-12.2 {
   789    db close
   790    sqlite3 db test.db
   791    execsql {
   792      PRAGMA synchronous = normal;
   793      UPDATE t1 SET y = 0 WHERE x = 'A';
   794    }
   795    list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044]
   796  } {3 1}
   797  do_test wal-12.3 {
   798    execsql { INSERT INTO t2 VALUES('B', 1) }
   799    list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044]
   800  } {3 2}
   801  do_test wal-12.4 {
   802    forcecopy test.db test2.db
   803    forcecopy test.db-wal test2.db-wal
   804    sqlite3_wal db2 test2.db
   805    execsql { SELECT * FROM t2 } db2
   806  } {B 1}
   807  db2 close
   808  do_test wal-12.5 {
   809    execsql {
   810      PRAGMA wal_checkpoint;
   811      UPDATE t2 SET y = 2 WHERE x = 'B'; 
   812      PRAGMA wal_checkpoint;
   813      UPDATE t1 SET y = 1 WHERE x = 'A';
   814      PRAGMA wal_checkpoint;
   815      UPDATE t1 SET y = 0 WHERE x = 'A';
   816    }
   817    execsql {  SELECT * FROM t2 }
   818  } {B 2}
   819  do_test wal-12.6 {
   820    forcecopy test.db test2.db
   821    forcecopy test.db-wal test2.db-wal
   822    sqlite3_wal db2 test2.db
   823    execsql { SELECT * FROM t2 } db2
   824  } {B 2}
   825  db2 close
   826  db close
   827  
   828  #-------------------------------------------------------------------------
   829  # Check a fun corruption case has been fixed.
   830  #
   831  # The problem was that after performing a checkpoint using a connection
   832  # that had an out-of-date pager-cache, the next time the connection was
   833  # used it did not realize the cache was out-of-date and proceeded to
   834  # operate with an inconsistent cache. Leading to corruption.
   835  #
   836  catch { db close }
   837  catch { db2 close }
   838  catch { db3 close }
   839  forcedelete test.db test.db-wal
   840  sqlite3 db test.db
   841  sqlite3 db2 test.db
   842  do_test wal-14 {
   843    execsql {
   844      PRAGMA journal_mode = WAL;
   845      CREATE TABLE t1(a PRIMARY KEY, b);
   846      INSERT INTO t1 VALUES(randomblob(10), randomblob(100));
   847      INSERT INTO t1 SELECT randomblob(10), randomblob(100) FROM t1;
   848      INSERT INTO t1 SELECT randomblob(10), randomblob(100) FROM t1;
   849      INSERT INTO t1 SELECT randomblob(10), randomblob(100) FROM t1;
   850    }
   851  
   852    db2 eval { 
   853      INSERT INTO t1 SELECT randomblob(10), randomblob(100);
   854      INSERT INTO t1 SELECT randomblob(10), randomblob(100);
   855      INSERT INTO t1 SELECT randomblob(10), randomblob(100);
   856      INSERT INTO t1 SELECT randomblob(10), randomblob(100);
   857    }
   858  
   859    # After executing the "PRAGMA wal_checkpoint", connection [db] was being
   860    # left with an inconsistent cache. Running the CREATE INDEX statement
   861    # in this state led to database corruption.
   862    catchsql { 
   863      PRAGMA wal_checkpoint;
   864      CREATE INDEX i1 on t1(b);
   865    }
   866     
   867    db2 eval { PRAGMA integrity_check }
   868  } {ok}
   869  
   870  catch { db close }
   871  catch { db2 close }
   872  
   873  #-------------------------------------------------------------------------
   874  # The following block of tests - wal-15.* - focus on testing the 
   875  # implementation of the sqlite3_wal_checkpoint() interface.
   876  #
   877  forcedelete test.db test.db-wal
   878  sqlite3 db test.db
   879  do_test wal-15.1 {
   880    execsql {
   881      PRAGMA auto_vacuum = 0;
   882      PRAGMA page_size = 1024;
   883      PRAGMA journal_mode = WAL;
   884    }
   885    execsql {
   886      CREATE TABLE t1(a, b);
   887      INSERT INTO t1 VALUES(1, 2);
   888    }
   889  } {}
   890  
   891  # Test that an error is returned if the database name is not recognized
   892  #
   893  do_test wal-15.2.1 {
   894    sqlite3_wal_checkpoint db aux
   895  } {SQLITE_ERROR}
   896  do_test wal-15.2.2 {
   897    sqlite3_errcode db
   898  } {SQLITE_ERROR}
   899  do_test wal-15.2.3 {
   900    sqlite3_errmsg db
   901  } {unknown database: aux}
   902  
   903  # Test that an error is returned if an attempt is made to checkpoint
   904  # if a transaction is open on the database.
   905  #
   906  do_test wal-15.3.1 {
   907    execsql {
   908      BEGIN;
   909      INSERT INTO t1 VALUES(3, 4);
   910    }
   911    sqlite3_wal_checkpoint db main
   912  } {SQLITE_LOCKED}
   913  do_test wal-15.3.2 {
   914    sqlite3_errcode db
   915  } {SQLITE_LOCKED}
   916  do_test wal-15.3.3 {
   917    sqlite3_errmsg db
   918  } {database table is locked}
   919  
   920  # Earlier versions returned an error is returned if the db cannot be 
   921  # checkpointed because of locks held by another connection. Check that
   922  # this is no longer the case.
   923  #
   924  sqlite3 db2 test.db
   925  do_test wal-15.4.1 {
   926    execsql {
   927      BEGIN;
   928      SELECT * FROM t1;
   929    } db2
   930  } {1 2}
   931  do_test wal-15.4.2 {
   932    execsql { COMMIT }
   933    sqlite3_wal_checkpoint db
   934  } {SQLITE_OK}
   935  do_test wal-15.4.3 {
   936    sqlite3_errmsg db
   937  } {not an error}
   938  
   939  # After [db2] drops its lock, [db] may checkpoint the db.
   940  #
   941  do_test wal-15.4.4 {
   942    execsql { COMMIT } db2
   943    sqlite3_wal_checkpoint db
   944  } {SQLITE_OK}
   945  do_test wal-15.4.5 {
   946    sqlite3_errmsg db
   947  } {not an error}
   948  do_test wal-15.4.6 {
   949    file size test.db
   950  } [expr 1024*2]
   951  
   952  catch { db2 close }
   953  catch { db close }
   954  
   955  #-------------------------------------------------------------------------
   956  # The following block of tests - wal-16.* - test that if a NULL pointer or
   957  # an empty string is passed as the second argument of the wal_checkpoint()
   958  # API, an attempt is made to checkpoint all attached databases.
   959  #
   960  foreach {tn ckpt_cmd ckpt_res ckpt_main ckpt_aux} {
   961    1 {sqlite3_wal_checkpoint db}              SQLITE_OK     1 1
   962    2 {sqlite3_wal_checkpoint db ""}           SQLITE_OK     1 1
   963    3 {db eval "PRAGMA wal_checkpoint"}        {0 10 10}     1 1
   964  
   965    4 {sqlite3_wal_checkpoint db main}         SQLITE_OK     1 0
   966    5 {sqlite3_wal_checkpoint db aux}          SQLITE_OK     0 1
   967    6 {sqlite3_wal_checkpoint db temp}         SQLITE_OK     0 0
   968    7 {db eval "PRAGMA main.wal_checkpoint"}   {0 10 10}     1 0
   969    8 {db eval "PRAGMA aux.wal_checkpoint"}    {0 13 13}     0 1
   970    9 {db eval "PRAGMA temp.wal_checkpoint"}   {0 -1 -1}     0 0
   971  } {
   972    do_test wal-16.$tn.1 {
   973      forcedelete test2.db test2.db-wal test2.db-journal
   974      forcedelete test.db test.db-wal test.db-journal
   975  
   976      sqlite3 db test.db
   977      execsql {
   978        ATTACH 'test2.db' AS aux;
   979        PRAGMA main.auto_vacuum = 0;
   980        PRAGMA aux.auto_vacuum = 0;
   981        PRAGMA main.journal_mode = WAL;
   982        PRAGMA aux.journal_mode = WAL;
   983        PRAGMA main.synchronous = NORMAL;
   984        PRAGMA aux.synchronous = NORMAL;
   985      }
   986    } {wal wal}
   987  
   988    do_test wal-16.$tn.2 {
   989      execsql {
   990        CREATE TABLE main.t1(a, b, PRIMARY KEY(a, b));
   991        CREATE TABLE aux.t2(a, b, PRIMARY KEY(a, b));
   992  
   993        INSERT INTO t2 VALUES(1, randomblob(1000));
   994        INSERT INTO t2 VALUES(2, randomblob(1000));
   995        INSERT INTO t1 SELECT * FROM t2;
   996      }
   997    
   998      list [file size test.db] [file size test.db-wal]
   999    } [list [expr 1*1024] [wal_file_size 10 1024]]
  1000    do_test wal-16.$tn.3 {
  1001      list [file size test2.db] [file size test2.db-wal]
  1002    } [list [expr 1*1024] [wal_file_size 13 1024]]
  1003    
  1004    do_test wal-16.$tn.4 [list eval $ckpt_cmd] $ckpt_res
  1005    
  1006    do_test wal-16.$tn.5 {
  1007      list [file size test.db] [file size test.db-wal]
  1008    } [list [expr ($ckpt_main ? 7 : 1)*1024] [wal_file_size 10 1024]]
  1009  
  1010    do_test wal-16.$tn.6 {
  1011      list [file size test2.db] [file size test2.db-wal]
  1012    } [list [expr ($ckpt_aux ? 7 : 1)*1024] [wal_file_size 13 1024]]
  1013  
  1014    catch { db close }
  1015  }
  1016  
  1017  #-------------------------------------------------------------------------
  1018  # The following tests - wal-17.* - attempt to verify that the correct
  1019  # number of "padding" frames are appended to the log file when a transaction
  1020  # is committed in synchronous=FULL mode.
  1021  # 
  1022  # Do this by creating a database that uses 512 byte pages. Then writing
  1023  # a transaction that modifies 171 pages. In synchronous=NORMAL mode, this
  1024  # produces a log file of:
  1025  #
  1026  #   32 + (24+512)*171 = 90312 bytes.
  1027  #
  1028  # Slightly larger than 11*8192 = 90112 bytes.
  1029  #
  1030  # Run the test using various different sector-sizes. In each case, the
  1031  # WAL code should write the 90300 bytes of log file containing the 
  1032  # transaction, then append as may frames as are required to extend the
  1033  # log file so that no part of the next transaction will be written into
  1034  # a disk-sector used by transaction just committed.
  1035  #
  1036  set old_pending_byte [sqlite3_test_control_pending_byte 0x10000000]
  1037  catch { db close }
  1038  foreach {tn sectorsize logsize} "
  1039    1   128  [wal_file_size 172 512]
  1040    2   256  [wal_file_size 172 512]
  1041    3   512  [wal_file_size 172 512] 
  1042    4  1024  [wal_file_size 172 512]
  1043    5  2048  [wal_file_size 172 512]
  1044    6  4096  [wal_file_size 176 512]
  1045    7  8192  [wal_file_size 184 512]
  1046  " {
  1047    forcedelete test.db test.db-wal test.db-journal
  1048    sqlite3_simulate_device -sectorsize $sectorsize
  1049    sqlite3 db test.db -vfs devsym
  1050  
  1051    do_test wal-17.$tn.1 {
  1052      execsql {
  1053        PRAGMA auto_vacuum = 0;
  1054        PRAGMA page_size = 512;
  1055        PRAGMA cache_size = -2000;
  1056        PRAGMA journal_mode = WAL;
  1057        PRAGMA synchronous = FULL;
  1058      }
  1059      execsql {
  1060        BEGIN;
  1061        CREATE TABLE t(x);
  1062      }
  1063      for {set i 0} {$i<166} {incr i} {
  1064        execsql { INSERT INTO t VALUES(randomblob(400)) }
  1065      }
  1066      execsql COMMIT
  1067  
  1068      file size test.db-wal
  1069    } $logsize
  1070  
  1071    do_test wal-17.$tn.2 {
  1072      file size test.db
  1073    } 512
  1074  
  1075    do_test wal-17.$tn.3 {
  1076      db close
  1077      file size test.db
  1078    } [expr 512*171]
  1079  }
  1080  sqlite3_test_control_pending_byte $old_pending_byte
  1081  
  1082  #-------------------------------------------------------------------------
  1083  # This test - wal-18.* - verifies a couple of specific conditions that
  1084  # may be encountered while recovering a log file are handled correctly:
  1085  #
  1086  #   wal-18.1.* When the first 32-bits of a frame checksum is correct but 
  1087  #              the second 32-bits are false, and
  1088  #
  1089  #   wal-18.2.* When the page-size field that occurs at the start of a log
  1090  #              file is a power of 2 greater than 16384 or smaller than 512.
  1091  #
  1092  forcedelete test.db test.db-wal test.db-journal
  1093  do_test wal-18.0 {
  1094    sqlite3 db test.db
  1095    execsql {
  1096      PRAGMA page_size = 1024;
  1097      PRAGMA auto_vacuum = 0;
  1098      PRAGMA journal_mode = WAL;
  1099      PRAGMA synchronous = OFF;
  1100  
  1101      CREATE TABLE t1(a, b, UNIQUE(a, b));
  1102      INSERT INTO t1 VALUES(0, 0);
  1103      PRAGMA wal_checkpoint;
  1104  
  1105      INSERT INTO t1 VALUES(1, 2);          -- frames 1 and 2
  1106      INSERT INTO t1 VALUES(3, 4);          -- frames 3 and 4
  1107      INSERT INTO t1 VALUES(5, 6);          -- frames 5 and 6
  1108    }
  1109  
  1110    forcecopy test.db testX.db
  1111    forcecopy test.db-wal testX.db-wal
  1112    db close
  1113    list [file size testX.db] [file size testX.db-wal]
  1114  } [list [expr 3*1024] [wal_file_size 6 1024]]
  1115  
  1116  unset -nocomplain nFrame result
  1117  foreach {nFrame result} {
  1118           0      {0 0}
  1119           1      {0 0}
  1120           2      {0 0 1 2}
  1121           3      {0 0 1 2}
  1122           4      {0 0 1 2 3 4}
  1123           5      {0 0 1 2 3 4}
  1124           6      {0 0 1 2 3 4 5 6}
  1125  } {
  1126    do_test wal-18.1.$nFrame {
  1127      forcecopy testX.db test.db
  1128      forcecopy testX.db-wal test.db-wal
  1129  
  1130      hexio_write test.db-wal [expr 24 + $nFrame*(24+1024) + 20] 00000000
  1131  
  1132      sqlite3 db test.db
  1133      execsql { 
  1134        SELECT * FROM t1;
  1135        PRAGMA integrity_check; 
  1136      }
  1137    } [concat $result ok]
  1138    db close
  1139  } 
  1140  
  1141  proc randomblob {pgsz} {
  1142    sqlite3 rbdb :memory:
  1143    set blob [rbdb one {SELECT randomblob($pgsz)}]
  1144    rbdb close
  1145    set blob
  1146  }
  1147  
  1148  proc logcksum {ckv1 ckv2 blob} {
  1149    upvar $ckv1 c1
  1150    upvar $ckv2 c2
  1151  
  1152    # Since the magic number at the start of the -wal file header is
  1153    # 931071618 that indicates that the content should always be read as
  1154    # little-endian.
  1155    # 
  1156    set scanpattern i*
  1157  
  1158    binary scan $blob $scanpattern values
  1159    foreach {v1 v2} $values {
  1160      set c1 [expr {($c1 + $v1 + $c2)&0xFFFFFFFF}]
  1161      set c2 [expr {($c2 + $v2 + $c1)&0xFFFFFFFF}]
  1162    }
  1163  }
  1164  
  1165  forcecopy test.db testX.db
  1166  foreach {tn pgsz works} { 
  1167    1    128    0
  1168    2    256    0
  1169    3    512    1
  1170    4   1024    1
  1171    5   2048    1
  1172    6   4096    1
  1173    7   8192    1
  1174    8  16384    1
  1175    9  32768    1
  1176   10  65536    1
  1177   11 131072    0
  1178   11   1016    0
  1179  } {
  1180  
  1181    if {$::SQLITE_MAX_PAGE_SIZE < $pgsz} {
  1182      set works 0
  1183    }
  1184  
  1185    for {set pg 1} {$pg <= 3} {incr pg} {
  1186      forcecopy testX.db test.db
  1187      forcedelete test.db-wal
  1188    
  1189      # Check that the database now exists and consists of three pages. And
  1190      # that there is no associated wal file.
  1191      #
  1192      do_test wal-18.2.$tn.$pg.1 { file exists test.db-wal } 0
  1193      do_test wal-18.2.$tn.$pg.2 { file exists test.db } 1
  1194      do_test wal-18.2.$tn.$pg.3 { file size test.db } [expr 1024*3]
  1195    
  1196      do_test wal-18.2.$tn.$pg.4 {
  1197  
  1198        # Create a wal file that contains a single frame (database page
  1199        # number $pg) with the commit flag set. The frame checksum is
  1200        # correct, but the contents of the database page are corrupt.
  1201        #
  1202        # The page-size in the log file header is set to $pgsz. If the
  1203        # WAL code considers $pgsz to be a valid SQLite database file page-size,
  1204        # the database will be corrupt (because the garbage frame contents
  1205        # will be treated as valid content). If $pgsz is invalid (too small
  1206        # or too large), the db will not be corrupt as the log file will
  1207        # be ignored.
  1208        #
  1209        set walhdr [binary format IIIIII 931071618 3007000 $pgsz 1234 22 23]
  1210        set framebody [randomblob $pgsz]
  1211        set framehdr  [binary format IIII $pg 5 22 23]
  1212        set c1 0
  1213        set c2 0
  1214        logcksum c1 c2 $walhdr
  1215  
  1216        append walhdr [binary format II $c1 $c2]
  1217        logcksum c1 c2 [string range $framehdr 0 7]
  1218        logcksum c1 c2 $framebody
  1219        set framehdr [binary format IIIIII $pg 5 22 23 $c1 $c2]
  1220  
  1221        set fd [open test.db-wal w]
  1222        fconfigure $fd -encoding binary -translation binary
  1223        puts -nonewline $fd $walhdr
  1224        puts -nonewline $fd $framehdr
  1225        puts -nonewline $fd $framebody
  1226        close $fd
  1227    
  1228        file size test.db-wal
  1229      } [wal_file_size 1 $pgsz]
  1230    
  1231      do_test wal-18.2.$tn.$pg.5 {
  1232        sqlite3 db test.db
  1233        set rc [catch { db one {PRAGMA integrity_check} } msg]
  1234        expr { $rc!=0 || $msg!="ok" }
  1235      } $works
  1236    
  1237      db close
  1238    }
  1239  }
  1240  
  1241  #-------------------------------------------------------------------------
  1242  # The following test - wal-19.* - fixes a bug that was present during
  1243  # development.
  1244  #
  1245  # When a database connection in WAL mode is closed, it attempts an
  1246  # EXCLUSIVE lock on the database file. If the lock is obtained, the
  1247  # connection knows that it is the last connection to disconnect from
  1248  # the database, so it runs a checkpoint operation. The bug was that
  1249  # the connection was not updating its private copy of the wal-index 
  1250  # header before doing so, meaning that it could checkpoint an old
  1251  # snapshot.
  1252  #
  1253  do_test wal-19.1 {
  1254    forcedelete test.db test.db-wal test.db-journal
  1255    sqlite3 db test.db
  1256    sqlite3 db2 test.db
  1257    execsql {
  1258      PRAGMA journal_mode = WAL;
  1259      CREATE TABLE t1(a, b);
  1260      INSERT INTO t1 VALUES(1, 2);
  1261      INSERT INTO t1 VALUES(3, 4);
  1262    }
  1263    execsql { SELECT * FROM t1 } db2
  1264  } {1 2 3 4}
  1265  do_test wal-19.2 {
  1266    execsql {
  1267      INSERT INTO t1 VALUES(5, 6);
  1268      SELECT * FROM t1;
  1269    }
  1270  } {1 2 3 4 5 6}
  1271  do_test wal-19.3 {
  1272    db close
  1273    db2 close
  1274    file exists test.db-wal
  1275  } {0}
  1276  do_test wal-19.4 {
  1277    # When the bug was present, the following was returning {1 2 3 4} only,
  1278    # as [db2] had an out-of-date copy of the wal-index header when it was
  1279    # closed.
  1280    #
  1281    sqlite3 db test.db
  1282    execsql { SELECT * FROM t1 }
  1283  } {1 2 3 4 5 6}
  1284  
  1285  #-------------------------------------------------------------------------
  1286  # This test - wal-20.* - uses two connections. One in this process and
  1287  # the other in an external process. The procedure is:
  1288  #
  1289  #   1. Using connection 1, create the database schema.
  1290  #
  1291  #   2. Using connection 2 (in an external process), add so much
  1292  #      data to the database without checkpointing that a wal-index 
  1293  #      larger than 64KB is required.
  1294  #
  1295  #   3. Using connection 1, checkpoint the database. Make sure all
  1296  #      the data is present and the database is not corrupt.
  1297  #
  1298  # At one point, SQLite was failing to grow the mapping of the wal-index
  1299  # file in step 3 and the checkpoint was corrupting the database file.
  1300  #
  1301  if {[permutation]!="unix-excl"} {
  1302    do_test wal-20.1 {
  1303      catch {db close}
  1304      forcedelete test.db test.db-wal test.db-journal
  1305      sqlite3 db test.db
  1306      execsql {
  1307        PRAGMA journal_mode = WAL;
  1308        CREATE TABLE t1(x);
  1309        INSERT INTO t1 VALUES(randomblob(900));
  1310        SELECT count(*) FROM t1;
  1311      }
  1312    } {wal 1}
  1313    do_test wal-20.2 {
  1314      set ::buddy [launch_testfixture]
  1315      testfixture $::buddy {
  1316        sqlite3 db test.db
  1317        db transaction { db eval {
  1318          PRAGMA wal_autocheckpoint = 0;
  1319          INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 2 */
  1320          INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 4 */
  1321          INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 8 */
  1322          INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 16 */
  1323          INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 32 */
  1324          INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 64 */
  1325          INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 128 */
  1326          INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 256 */
  1327          INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 512 */
  1328          INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 1024 */
  1329          INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 2048 */
  1330          INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 4096 */
  1331          INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 8192 */
  1332          INSERT INTO t1 SELECT randomblob(900) FROM t1;       /* 16384 */
  1333        } }
  1334      }
  1335    } {0}
  1336    do_test wal-20.3 {
  1337      close $::buddy
  1338      execsql { PRAGMA wal_checkpoint }
  1339      execsql { SELECT count(*) FROM t1 }
  1340    } {16384}
  1341    do_test wal-20.4 {
  1342      db close
  1343      sqlite3 db test.db
  1344      execsql { SELECT count(*) FROM t1 }
  1345    } {16384}
  1346    integrity_check wal-20.5
  1347  }
  1348  
  1349  catch { db2 close }
  1350  catch { db close }
  1351  
  1352  do_test wal-21.1 {
  1353    faultsim_delete_and_reopen
  1354    execsql { 
  1355      PRAGMA journal_mode = WAL;
  1356      CREATE TABLE t1(a, b);
  1357      INSERT INTO t1 VALUES(1, 2);
  1358      INSERT INTO t1 VALUES(3, 4);
  1359      INSERT INTO t1 VALUES(5, 6);
  1360      INSERT INTO t1 VALUES(7, 8);
  1361      INSERT INTO t1 VALUES(9, 10);
  1362      INSERT INTO t1 VALUES(11, 12);
  1363    }
  1364  } {wal}
  1365  do_test wal-21.2 {
  1366    execsql { 
  1367      PRAGMA cache_size = 10;
  1368      PRAGMA wal_checkpoint;
  1369      BEGIN;
  1370        SAVEPOINT s;
  1371          INSERT INTO t1 SELECT randomblob(900), randomblob(900) FROM t1;
  1372        ROLLBACK TO s;
  1373      COMMIT;
  1374    }
  1375    execsql { SELECT * FROM t1 }
  1376  } {1 2 3 4 5 6 7 8 9 10 11 12}
  1377  do_test wal-21.3 {
  1378    execsql { PRAGMA integrity_check }
  1379  } {ok}
  1380  
  1381  #-------------------------------------------------------------------------
  1382  # Test reading and writing of databases with different page-sizes.
  1383  #
  1384  incr ::do_not_use_codec
  1385  foreach pgsz {512 1024 2048 4096 8192 16384 32768 65536} {
  1386    do_multiclient_test tn [string map [list %PGSZ% $pgsz] {
  1387      do_test wal-22.%PGSZ%.$tn.1 {
  1388        sql1 {
  1389          PRAGMA main.page_size = %PGSZ%;
  1390          PRAGMA auto_vacuum = 0;
  1391          PRAGMA journal_mode = WAL;
  1392          CREATE TABLE t1(x UNIQUE);
  1393          INSERT INTO t1 SELECT randomblob(800);
  1394          INSERT INTO t1 SELECT randomblob(800);
  1395          INSERT INTO t1 SELECT randomblob(800);
  1396        }
  1397      } {wal}
  1398      do_test wal-22.%PGSZ%.$tn.2 { sql2 { PRAGMA integrity_check } } {ok}
  1399      do_test wal-22.%PGSZ%.$tn.3 {
  1400        sql1 {PRAGMA wal_checkpoint}
  1401        expr {[file size test.db] % %PGSZ%}
  1402      } {0}
  1403    }]
  1404  }
  1405  incr ::do_not_use_codec -1
  1406  
  1407  #-------------------------------------------------------------------------
  1408  # Test that when 1 or more pages are recovered from a WAL file, 
  1409  # sqlite3_log() is invoked to report this to the user.
  1410  #
  1411  ifcapable curdir {
  1412    set walfile [file nativename [file join [get_pwd] test.db-wal]]
  1413  } else {
  1414    set walfile test.db-wal
  1415  }
  1416  catch {db close}
  1417  forcedelete test.db
  1418  do_test wal-23.1 {
  1419    faultsim_delete_and_reopen
  1420    execsql {
  1421      CREATE TABLE t1(a, b);
  1422      PRAGMA journal_mode = WAL;
  1423      INSERT INTO t1 VALUES(1, 2);
  1424      INSERT INTO t1 VALUES(3, 4);
  1425    }
  1426    faultsim_save_and_close
  1427  
  1428    sqlite3_shutdown
  1429    test_sqlite3_log [list lappend ::log]
  1430    set ::log [list]
  1431    sqlite3 db test.db
  1432    execsql { SELECT * FROM t1 }
  1433  } {1 2 3 4}
  1434  do_test wal-23.2 { set ::log } {}
  1435  
  1436  do_test wal-23.3 {
  1437    db close
  1438    set ::log [list]
  1439    faultsim_restore_and_reopen
  1440    execsql { SELECT * FROM t1 }
  1441  } {1 2 3 4}
  1442  do_test wal-23.4 { 
  1443    set ::log 
  1444  } [list SQLITE_NOTICE_RECOVER_WAL \
  1445      "recovered 2 frames from WAL file $walfile"]
  1446  
  1447  
  1448  ifcapable autovacuum {
  1449    # This block tests that if the size of a database is reduced by a 
  1450    # transaction (because of an incremental or auto-vacuum), that no
  1451    # data is written to the WAL file for the truncated pages as part
  1452    # of the commit. e.g. if a transaction reduces the size of a database
  1453    # to N pages, data for page N+1 should not be written to the WAL file 
  1454    # when committing the transaction. At one point such data was being 
  1455    # written.
  1456    #
  1457    catch {db close}
  1458    forcedelete test.db
  1459    sqlite3 db test.db
  1460    do_execsql_test 24.1 {
  1461      PRAGMA auto_vacuum = 2;
  1462      PRAGMA journal_mode = WAL;
  1463      PRAGMA page_size = 1024;
  1464      CREATE TABLE t1(x);
  1465      INSERT INTO t1 VALUES(randomblob(5000));
  1466      INSERT INTO t1 SELECT * FROM t1;
  1467      INSERT INTO t1 SELECT * FROM t1;
  1468      INSERT INTO t1 SELECT * FROM t1;
  1469      INSERT INTO t1 SELECT * FROM t1;
  1470    } {wal}
  1471    do_test 24.2 { 
  1472      execsql {
  1473        DELETE FROM t1;
  1474        PRAGMA wal_checkpoint;
  1475      }
  1476      db close
  1477      sqlite3 db test.db
  1478      file exists test.db-wal
  1479    } 0
  1480    do_test 24.3 {
  1481      file size test.db
  1482    } [expr 84 * 1024]
  1483    do_test 24.4 {
  1484      execsql { 
  1485        PRAGMA cache_size = 200;
  1486        PRAGMA incremental_vacuum;
  1487        PRAGMA wal_checkpoint;
  1488      }
  1489      file size test.db
  1490    } [expr 3 * 1024]
  1491  
  1492    # WAL file now contains a single frame - the new root page for table t1.
  1493    # It would be two frames (the new root page and a padding frame) if the
  1494    # ZERO_DAMAGE flag were not set.
  1495    do_test 24.5 {
  1496      file size test.db-wal
  1497    } [wal_file_size 1 1024]
  1498  }
  1499  
  1500  db close
  1501  sqlite3_shutdown
  1502  test_sqlite3_log
  1503  sqlite3_initialize
  1504  
  1505  # Make sure PRAGMA journal_mode=WAL works with ATTACHED databases in
  1506  # all journal modes.
  1507  #
  1508  foreach mode {OFF MEMORY PERSIST DELETE TRUNCATE WAL} {
  1509    delete_file test.db test2.db
  1510    sqlite3 db test.db
  1511    do_test wal-25.$mode {
  1512      db eval "PRAGMA journal_mode=$mode"
  1513      db eval {ATTACH 'test2.db' AS t2; PRAGMA journal_mode=WAL;}
  1514    } {wal}
  1515    db close
  1516  }
  1517  
  1518  # 2021-03-10 forum post https://sqlite.org/forum/forumpost/a006d86f72
  1519  #
  1520  file delete test.db
  1521  sqlite3 db test.db
  1522  db eval {PRAGMA journal_mode=WAL}
  1523  for {set i 0} {$i<$SQLITE_MAX_ATTACHED} {incr i} {
  1524    do_test wal-26.1.$i {
  1525      file delete attached-$i.db
  1526      db eval "ATTACH 'attached-$i.db' AS a$i;"
  1527      db eval "PRAGMA a$i.journal_mode=WAL;"
  1528      db eval "CREATE TABLE a$i.t$i (x);"
  1529      db eval "INSERT INTO t$i VALUES(zeroblob(10000));"
  1530      db eval "DELETE FROM t$i;"
  1531      db eval "INSERT INTO t$i VALUES(randomblob(10000));"
  1532      expr {[file size attached-$i.db-wal]>10000}
  1533    } {1}
  1534  }
  1535  for {set i [expr {$SQLITE_MAX_ATTACHED-1}]} {$i>=0} {incr i -1} {
  1536    do_test wal-26.2.$i {
  1537      db eval "PRAGMA a$i.wal_checkpoint(TRUNCATE);"
  1538      file size attached-$i.db-wal
  1539    } {0}
  1540    for {set j 0} {$j<$i} {incr j} {
  1541      do_test wal-26.2.$i.$j {
  1542        expr {[file size attached-$j.db-wal]>10000}
  1543      } {1}
  1544    }
  1545  }
  1546  db close
  1547  
  1548  
  1549  test_restore_config_pagecache
  1550  finish_test