Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add new test file e_walhook.test. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
2eb6d3e4fbe388ef28e4b7b846e9e8a4 |
User & Date: | dan 2014-12-10 20:29:49.614 |
Context
2014-12-10
| ||
20:57 | Fix a typo causing a test error in e_walhook.test. (check-in: d9f916ba09 user: dan tags: trunk) | |
20:29 | Add new test file e_walhook.test. (check-in: 2eb6d3e4fb user: dan tags: trunk) | |
17:34 | Revise mutex handling by the sqlite3_win32_reset_heap() function. (check-in: eacb3b7baa user: mistachkin tags: trunk) | |
Changes
Changes to src/sqlite.h.in.
︙ | ︙ | |||
7176 7177 7178 7179 7180 7181 7182 | */ void sqlite3_log(int iErrCode, const char *zFormat, ...); /* ** CAPI3REF: Write-Ahead Log Commit Hook ** ** ^The [sqlite3_wal_hook()] function is used to register a callback that | | < < | | | 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 | */ void sqlite3_log(int iErrCode, const char *zFormat, ...); /* ** CAPI3REF: Write-Ahead Log Commit Hook ** ** ^The [sqlite3_wal_hook()] function is used to register a callback that ** is invoked each time data is committed to a database in wal mode. ** ** ^(The callback is invoked by SQLite after the commit has taken place and ** the associated write-lock on the database released)^, so the implementation ** may read, write or [checkpoint] the database as required. ** ** ^The first parameter passed to the callback function when it is invoked ** is a copy of the third parameter passed to sqlite3_wal_hook() when ** registering the callback. ^The second is a copy of the database handle. ** ^The third parameter is the name of the database that was written to - ** either "main" or the name of an [ATTACH]-ed database. ^The fourth parameter |
︙ | ︙ |
Changes to src/tclsqlite.c.
︙ | ︙ | |||
631 632 633 634 635 636 637 638 639 640 641 642 643 644 | ){ int ret = SQLITE_OK; Tcl_Obj *p; SqliteDb *pDb = (SqliteDb*)clientData; Tcl_Interp *interp = pDb->interp; assert(pDb->pWalHook); p = Tcl_DuplicateObj(pDb->pWalHook); Tcl_IncrRefCount(p); Tcl_ListObjAppendElement(interp, p, Tcl_NewStringObj(zDb, -1)); Tcl_ListObjAppendElement(interp, p, Tcl_NewIntObj(nEntry)); if( TCL_OK!=Tcl_EvalObjEx(interp, p, 0) || TCL_OK!=Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &ret) ){ | > | 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 | ){ int ret = SQLITE_OK; Tcl_Obj *p; SqliteDb *pDb = (SqliteDb*)clientData; Tcl_Interp *interp = pDb->interp; assert(pDb->pWalHook); assert( db==pDb->db ); p = Tcl_DuplicateObj(pDb->pWalHook); Tcl_IncrRefCount(p); Tcl_ListObjAppendElement(interp, p, Tcl_NewStringObj(zDb, -1)); Tcl_ListObjAppendElement(interp, p, Tcl_NewIntObj(nEntry)); if( TCL_OK!=Tcl_EvalObjEx(interp, p, 0) || TCL_OK!=Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &ret) ){ |
︙ | ︙ |
Added test/e_walhook.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | # 2014 December 04 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/wal_common.tcl set testprefix e_walhook # EVIDENCE-OF: R-00752-43975 The sqlite3_wal_hook() function is used to # register a callback that is invoked each time data is committed to a # database in wal mode. # # 1.1: shows that the wal-hook is not invoked in rollback mode. # 1.2: but is invoked in wal mode. # set ::wal_hook_count 0 proc my_wal_hook {args} { incr ::wal_hook_count return 0 } do_test 1.1.1 { db wal_hook my_wal_hook execsql { CREATE TABLE t1(x); INSERT INTO t1 VALUES(1); } set ::wal_hook_count } 0 do_test 1.1.2 { execsql { PRAGMA journal_mode = wal } set ::wal_hook_count } 0 do_test 1.3 { execsql { INSERT INTO t1 VALUES(2) } set wal_hook_count } 1 do_test 1.4 { execsql { BEGIN; INSERT INTO t1 VALUES(3); INSERT INTO t1 VALUES(4); COMMIT; } set wal_hook_count } 2 # EVIDENCE-OF: R-65366-15139 The callback is invoked by SQLite after the # commit has taken place and the associated write-lock on the database # released # set ::read_ok 0 proc my_wal_hook {args} { sqlite3 db2 test.db if {[db2 eval { SELECT * FROM t1 }] == "1 2 3 4 5"} { set ::read_ok 1 } db2 close } do_test 2.1 { execsql { INSERT INTO t1 VALUES(5) } set ::read_ok } 1 # EVIDENCE-OF: R-44294-52863 The third parameter is the name of the # database that was written to - either "main" or the name of an # ATTACH-ed database. # # EVIDENCE-OF: R-18913-19355 The fourth parameter is the number of pages # currently in the write-ahead log file, including those that were just # committed. # set ::wal_hook_args [list] proc my_wal_hook {dbname nEntry} { set ::wal_hook_args [list $dbname $nEntry] } forcedelete test.db2 do_test 3.0 { execsql { ATTACH 'test.db2' AS aux; CREATE TABLE aux.t2(x); PRAGMA aux.journal_mode = wal; } } {wal} # Database "aux" do_test 3.1.1 { set wal_hook_args [list] execsql { INSERT INTO t2 VALUES('a') } } {} do_test 3.1.2 { set wal_hook_args } [list aux [wal_frame_count test.db2-wal 1024]] # Database "main" do_test 3.2.1 { set wal_hook_args [list] execsql { INSERT INTO t1 VALUES(6) } } {} do_test 3.1.2 { set wal_hook_args } [list main [wal_frame_count test.db-wal 1024]] # EVIDENCE-OF: R-14034-00929 If an error code is returned, that error # will propagate back up through the SQLite code base to cause the # statement that provoked the callback to report an error, though the # commit will have still occurred. # proc my_wal_hook {args} { return 1 ;# SQLITE_ERROR } do_catchsql_test 4.1 { INSERT INTO t1 VALUES(7) } {1 {SQL logic error or missing database}} proc my_wal_hook {args} { return 5 ;# SQLITE_BUSY } do_catchsql_test 4.2 { INSERT INTO t1 VALUES(8) } {1 {database is locked}} proc my_wal_hook {args} { return 14 ;# SQLITE_CANTOPEN } do_catchsql_test 4.3 { INSERT INTO t1 VALUES(9) } {1 {unable to open database file}} do_execsql_test 4.4 { SELECT * FROM t1 } {1 2 3 4 5 6 7 8 9} # EVIDENCE-OF: R-10466-53920 Calling sqlite3_wal_hook() replaces any # previously registered write-ahead log callback. set ::old_wal_hook 0 proc my_old_wal_hook {args} { incr ::old_wal_hook return 0 } db wal_hook my_old_wal_hook do_test 5.1 { execsql { INSERT INTO t1 VALUES(10) } set ::old_wal_hook } {1} # Replace old_wal_hook. Observe that it is not invoked after it has # been replaced. proc my_new_wal_hook {args} { return 0 } db wal_hook my_new_wal_hook do_test 5.2 { execsql { INSERT INTO t1 VALUES(11) } set ::old_wal_hook } {1} # EVIDENCE-OF: R-42842-27162 Note that the sqlite3_wal_autocheckpoint() # interface and the wal_autocheckpoint pragma both invoke # sqlite3_wal_hook() and will those overwrite any prior # sqlite3_wal_hook() settings. # set ::old_wal_hook 0 proc my_old_wal_hook {args} { incr ::old_wal_hook ; return 0 } do_test 6.1.1 { execsql { INSERT INTO t1 VALUES(12) } set ::old_wal_hook } {1} do_test 6.1.2 { execsql { PRAGA wal_autocheckpoint = 1000 } execsql { INSERT INTO t1 VALUES(12) } set ::old_wal_hook } {1} # EVIDENCE-OF: R-52629-38967 The first parameter passed to the callback # function when it is invoked is a copy of the third parameter passed to # sqlite3_wal_hook() when registering the callback. # # This is tricky to test using the tcl interface. However, the # mechanism used to invoke the tcl script registered as a wal-hook # depends on the context pointer being correctly passed through. And # since multiple different wal-hook scripts have been successfully # invoked by this test script, consider this tested. # # EVIDENCE-OF: R-23378-42536 The second is a copy of the database # handle. # # There is an assert() in the C wal-hook used by tclsqlite.c to # prove this. And that hook has been invoked multiple times when # running this script. So consider this requirement tested as well. # finish_test |