OLD | NEW |
(Empty) | |
| 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 or missing database}} |
| 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 |
OLD | NEW |