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

     1  # 2014 December 04
     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  
    13  set testdir [file dirname $argv0]
    14  source $testdir/tester.tcl
    15  source $testdir/wal_common.tcl
    16  set testprefix e_walhook
    17  
    18  
    19  # EVIDENCE-OF: R-00752-43975 The sqlite3_wal_hook() function is used to
    20  # register a callback that is invoked each time data is committed to a
    21  # database in wal mode.
    22  #
    23  #   1.1: shows that the wal-hook is not invoked in rollback mode.
    24  #   1.2: but is invoked in wal mode.
    25  #
    26  set ::wal_hook_count 0
    27  proc my_wal_hook {args} {
    28    incr ::wal_hook_count
    29    return 0
    30  }
    31  
    32  do_test 1.1.1 {
    33    db wal_hook my_wal_hook
    34    execsql {
    35      CREATE TABLE t1(x);
    36      INSERT INTO t1 VALUES(1);
    37    }
    38    set ::wal_hook_count
    39  } 0
    40  do_test 1.1.2 {
    41    execsql { PRAGMA journal_mode = wal }
    42    set ::wal_hook_count
    43  } 0
    44  
    45  do_test 1.3 {
    46    execsql { INSERT INTO t1 VALUES(2) }
    47    set wal_hook_count
    48  } 1
    49  
    50  do_test 1.4 {
    51    execsql { 
    52      BEGIN;
    53        INSERT INTO t1 VALUES(3);
    54        INSERT INTO t1 VALUES(4);
    55      COMMIT;
    56    }
    57    set wal_hook_count
    58  } 2
    59  
    60  # EVIDENCE-OF: R-65366-15139 The callback is invoked by SQLite after the
    61  # commit has taken place and the associated write-lock on the database
    62  # released
    63  #
    64  set ::read_ok 0
    65  proc my_wal_hook {args} {
    66    sqlite3 db2 test.db
    67    if {[db2 eval { SELECT * FROM t1 }] == "1 2 3 4 5"} {
    68      set ::read_ok 1
    69    }
    70    db2 close
    71  }
    72  do_test 2.1 {
    73    execsql { INSERT INTO t1 VALUES(5) }
    74    set ::read_ok
    75  } 1
    76  
    77  # EVIDENCE-OF: R-44294-52863 The third parameter is the name of the
    78  # database that was written to - either "main" or the name of an
    79  # ATTACH-ed database.
    80  #
    81  # EVIDENCE-OF: R-18913-19355 The fourth parameter is the number of pages
    82  # currently in the write-ahead log file, including those that were just
    83  # committed.
    84  #
    85  set ::wal_hook_args [list]
    86  proc my_wal_hook {dbname nEntry} {
    87    set ::wal_hook_args [list $dbname $nEntry]
    88  }
    89  forcedelete test.db2
    90  do_test 3.0 {
    91    execsql {
    92      ATTACH 'test.db2' AS aux;
    93      CREATE TABLE aux.t2(x);
    94      PRAGMA aux.journal_mode = wal;
    95    }
    96  } {wal}
    97  
    98  # Database "aux"
    99  do_test 3.1.1 {
   100    set wal_hook_args [list]
   101    execsql { INSERT INTO t2 VALUES('a') }
   102  } {}
   103  do_test 3.1.2 {
   104    set wal_hook_args
   105  } [list aux [wal_frame_count test.db2-wal 1024]]
   106  
   107  # Database "main"
   108  do_test 3.2.1 {
   109    set wal_hook_args [list]
   110    execsql { INSERT INTO t1 VALUES(6) }
   111  } {}
   112  do_test 3.1.2 {
   113    set wal_hook_args
   114  } [list main [wal_frame_count test.db-wal 1024]]
   115  
   116  # EVIDENCE-OF: R-14034-00929 If an error code is returned, that error
   117  # will propagate back up through the SQLite code base to cause the
   118  # statement that provoked the callback to report an error, though the
   119  # commit will have still occurred.
   120  #
   121  proc my_wal_hook {args} { return 1 ;# SQLITE_ERROR }
   122  do_catchsql_test 4.1 {
   123    INSERT INTO t1 VALUES(7)
   124  } {1 {SQL logic error}}
   125  
   126  proc my_wal_hook {args} { return 5 ;# SQLITE_BUSY }
   127  do_catchsql_test 4.2 {
   128    INSERT INTO t1 VALUES(8)
   129  } {1 {database is locked}}
   130  
   131  proc my_wal_hook {args} { return 14 ;# SQLITE_CANTOPEN }
   132  do_catchsql_test 4.3 {
   133    INSERT INTO t1 VALUES(9)
   134  } {1 {unable to open database file}}
   135  
   136  do_execsql_test 4.4 {
   137    SELECT * FROM t1
   138  } {1 2 3 4 5 6 7 8 9}
   139  
   140  # EVIDENCE-OF: R-10466-53920 Calling sqlite3_wal_hook() replaces any
   141  # previously registered write-ahead log callback.
   142  set ::old_wal_hook 0
   143  proc my_old_wal_hook {args} {
   144    incr ::old_wal_hook 
   145    return 0
   146  }
   147  db wal_hook my_old_wal_hook
   148  do_test 5.1 {
   149    execsql { INSERT INTO t1 VALUES(10) }
   150    set ::old_wal_hook
   151  } {1}
   152  
   153  # Replace old_wal_hook. Observe that it is not invoked after it has 
   154  # been replaced.
   155  proc my_new_wal_hook {args} { return 0 }
   156  db wal_hook my_new_wal_hook
   157  do_test 5.2 {
   158    execsql { INSERT INTO t1 VALUES(11) }
   159    set ::old_wal_hook
   160  } {1}
   161  
   162  
   163  
   164  # EVIDENCE-OF: R-57445-43425 Note that the sqlite3_wal_autocheckpoint()
   165  # interface and the wal_autocheckpoint pragma both invoke
   166  # sqlite3_wal_hook() and will overwrite any prior sqlite3_wal_hook()
   167  # settings.
   168  #
   169  set ::old_wal_hook 0
   170  proc my_old_wal_hook {args} { incr ::old_wal_hook ; return 0 }
   171  db wal_hook my_old_wal_hook
   172  do_test 6.1.1 {
   173    execsql { INSERT INTO t1 VALUES(12) }
   174    set ::old_wal_hook
   175  } {1}
   176  do_test 6.1.2 {
   177    execsql { PRAGMA wal_autocheckpoint = 1000 }
   178    execsql { INSERT INTO t1 VALUES(12) }
   179    set ::old_wal_hook
   180  } {1}
   181  
   182  # EVIDENCE-OF: R-52629-38967 The first parameter passed to the callback
   183  # function when it is invoked is a copy of the third parameter passed to
   184  # sqlite3_wal_hook() when registering the callback.
   185  #
   186  #    This is tricky to test using the tcl interface. However, the
   187  #    mechanism used to invoke the tcl script registered as a wal-hook
   188  #    depends on the context pointer being correctly passed through. And
   189  #    since multiple different wal-hook scripts have been successfully
   190  #    invoked by this test script, consider this tested.
   191  #
   192  # EVIDENCE-OF: R-23378-42536 The second is a copy of the database
   193  # handle.
   194  #
   195  #    There is an assert() in the C wal-hook used by tclsqlite.c to
   196  #    prove this. And that hook has been invoked multiple times when
   197  #    running this script. So consider this requirement tested as well.
   198  #
   199  
   200  finish_test