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-42842-27162 Note that the sqlite3_wal_autocheckpoint() | |
165 # interface and the wal_autocheckpoint pragma both invoke | |
166 # sqlite3_wal_hook() and will those overwrite any prior | |
167 # sqlite3_wal_hook() 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 |