OLD | NEW |
1 # 2004 Jan 14 | 1 # 2004 Jan 14 |
2 # | 2 # |
3 # The author disclaims copyright to this source code. In place of | 3 # The author disclaims copyright to this source code. In place of |
4 # a legal notice, here is a blessing: | 4 # a legal notice, here is a blessing: |
5 # | 5 # |
6 # May you do good and not evil. | 6 # May you do good and not evil. |
7 # May you find forgiveness for yourself and forgive others. | 7 # May you find forgiveness for yourself and forgive others. |
8 # May you share freely, never taking more than you give. | 8 # May you share freely, never taking more than you give. |
9 # | 9 # |
10 #*********************************************************************** | 10 #*********************************************************************** |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 do_test hook-3.6 { | 67 do_test hook-3.6 { |
68 set commit_cnt {} | 68 set commit_cnt {} |
69 proc commit_hook {} { | 69 proc commit_hook {} { |
70 set ::commit_cnt [execsql {SELECT * FROM t2}] | 70 set ::commit_cnt [execsql {SELECT * FROM t2}] |
71 return 1 | 71 return 1 |
72 } | 72 } |
73 catchsql { | 73 catchsql { |
74 INSERT INTO t2 VALUES(6,7); | 74 INSERT INTO t2 VALUES(6,7); |
75 } | 75 } |
76 } {1 {constraint failed}} | 76 } {1 {constraint failed}} |
| 77 verify_ex_errcode hook-3.6b SQLITE_CONSTRAINT_COMMITHOOK |
77 do_test hook-3.7 { | 78 do_test hook-3.7 { |
78 set ::commit_cnt | 79 set ::commit_cnt |
79 } {1 2 2 3 3 4 4 5 5 6 6 7} | 80 } {1 2 2 3 3 4 4 5 5 6 6 7} |
80 do_test hook-3.8 { | 81 do_test hook-3.8 { |
81 execsql {SELECT * FROM t2} | 82 execsql {SELECT * FROM t2} |
82 } {1 2 2 3 3 4 4 5 5 6} | 83 } {1 2 2 3 3 4 4 5 5 6} |
83 | 84 |
84 # Test turnning off the commit hook | 85 # Test turnning off the commit hook |
85 # | 86 # |
86 do_test hook-3.9 { | 87 do_test hook-3.9 { |
87 db commit_hook {} | 88 db commit_hook {} |
88 set ::commit_cnt {} | 89 set ::commit_cnt {} |
89 execsql { | 90 execsql { |
90 INSERT INTO t2 VALUES(7,8); | 91 INSERT INTO t2 VALUES(7,8); |
91 } | 92 } |
92 set ::commit_cnt | 93 set ::commit_cnt |
93 } {} | 94 } {} |
94 | 95 |
95 # Ticket #3564. | 96 # Ticket #3564. |
96 # | 97 # |
97 do_test hook-3.10 { | 98 do_test hook-3.10 { |
98 file delete -force test2.db test2.db-journal | 99 forcedelete test2.db test2.db-journal |
99 sqlite3 db2 test2.db | 100 sqlite3 db2 test2.db |
100 proc commit_hook {} { | 101 proc commit_hook {} { |
101 set y [db2 one {SELECT y FROM t3 WHERE y>10}] | 102 set y [db2 one {SELECT y FROM t3 WHERE y>10}] |
102 return [expr {$y>10}] | 103 return [expr {$y>10}] |
103 } | 104 } |
104 db2 eval {CREATE TABLE t3(x,y)} | 105 db2 eval {CREATE TABLE t3(x,y)} |
105 db2 commit_hook commit_hook | 106 db2 commit_hook commit_hook |
106 catchsql {INSERT INTO t3 VALUES(1,2)} db2 | 107 catchsql {INSERT INTO t3 VALUES(1,2)} db2 |
107 catchsql {INSERT INTO t3 VALUES(11,12)} db2 | 108 catchsql {INSERT INTO t3 VALUES(11,12)} db2 |
108 catchsql {INSERT INTO t3 VALUES(3,4)} db2 | 109 catchsql {INSERT INTO t3 VALUES(3,4)} db2 |
(...skipping 10 matching lines...) Expand all Loading... |
119 # 4.1.* - Very simple tests. Test that the update hook is invoked correctly | 120 # 4.1.* - Very simple tests. Test that the update hook is invoked correctly |
120 # for INSERT, DELETE and UPDATE statements, including DELETE | 121 # for INSERT, DELETE and UPDATE statements, including DELETE |
121 # statements with no WHERE clause. | 122 # statements with no WHERE clause. |
122 # 4.2.* - Check that the update-hook is invoked for rows modified by trigger | 123 # 4.2.* - Check that the update-hook is invoked for rows modified by trigger |
123 # bodies. Also that the database name is correctly reported when | 124 # bodies. Also that the database name is correctly reported when |
124 # an attached database is modified. | 125 # an attached database is modified. |
125 # 4.3.* - Do some sorting, grouping, compound queries, population and | 126 # 4.3.* - Do some sorting, grouping, compound queries, population and |
126 # depopulation of indices, to make sure the update-hook is not | 127 # depopulation of indices, to make sure the update-hook is not |
127 # invoked incorrectly. | 128 # invoked incorrectly. |
128 # | 129 # |
| 130 # EVIDENCE-OF: R-21999-45122 The sqlite3_update_hook() interface |
| 131 # registers a callback function with the database connection identified |
| 132 # by the first argument to be invoked whenever a row is updated, |
| 133 # inserted or deleted in a rowid table. |
129 | 134 |
130 # Simple tests | 135 # Simple tests |
131 do_test hook-4.1.1 { | 136 do_test hook-4.1.1a { |
132 catchsql { | 137 catchsql { |
133 DROP TABLE t1; | 138 DROP TABLE t1; |
134 } | 139 } |
| 140 unset -nocomplain ::update_hook |
| 141 set ::update_hook {} |
| 142 db update_hook [list lappend ::update_hook] |
| 143 # |
| 144 # EVIDENCE-OF: R-52223-27275 The update hook is not invoked when |
| 145 # internal system tables are modified (i.e. sqlite_master and |
| 146 # sqlite_sequence). |
| 147 # |
135 execsql { | 148 execsql { |
136 CREATE TABLE t1(a INTEGER PRIMARY KEY, b); | 149 CREATE TABLE t1(a INTEGER PRIMARY KEY, b); |
| 150 CREATE TABLE t1w(a INT PRIMARY KEY, b) WITHOUT ROWID; |
| 151 } |
| 152 set ::update_hook |
| 153 } {} |
| 154 do_test hook-4.1.1b { |
| 155 execsql { |
137 INSERT INTO t1 VALUES(1, 'one'); | 156 INSERT INTO t1 VALUES(1, 'one'); |
138 INSERT INTO t1 VALUES(2, 'two'); | 157 INSERT INTO t1 VALUES(2, 'two'); |
139 INSERT INTO t1 VALUES(3, 'three'); | 158 INSERT INTO t1 VALUES(3, 'three'); |
| 159 INSERT INTO t1w SELECT * FROM t1; |
140 } | 160 } |
141 db update_hook [list lappend ::update_hook] | |
142 } {} | 161 } {} |
| 162 |
| 163 # EVIDENCE-OF: R-15506-57666 The second callback argument is one of |
| 164 # SQLITE_INSERT, SQLITE_DELETE, or SQLITE_UPDATE, depending on the |
| 165 # operation that caused the callback to be invoked. |
| 166 # |
| 167 # EVIDENCE-OF: R-29213-61195 The third and fourth arguments to the |
| 168 # callback contain pointers to the database and table name containing |
| 169 # the affected row. |
| 170 # |
| 171 # EVIDENCE-OF: R-30809-57812 The final callback parameter is the rowid |
| 172 # of the row. |
| 173 # |
143 do_test hook-4.1.2 { | 174 do_test hook-4.1.2 { |
| 175 set ::update_hook {} |
144 execsql { | 176 execsql { |
145 INSERT INTO t1 VALUES(4, 'four'); | 177 INSERT INTO t1 VALUES(4, 'four'); |
146 DELETE FROM t1 WHERE b = 'two'; | 178 DELETE FROM t1 WHERE b = 'two'; |
147 UPDATE t1 SET b = '' WHERE a = 1 OR a = 3; | 179 UPDATE t1 SET b = '' WHERE a = 1 OR a = 3; |
148 DELETE FROM t1 WHERE 1; -- Avoid the truncate optimization (for now) | 180 DELETE FROM t1 WHERE 1; -- Avoid the truncate optimization (for now) |
149 } | 181 } |
150 set ::update_hook | 182 set ::update_hook |
151 } [list \ | 183 } [list \ |
152 INSERT main t1 4 \ | 184 INSERT main t1 4 \ |
153 DELETE main t1 2 \ | 185 DELETE main t1 2 \ |
154 UPDATE main t1 1 \ | 186 UPDATE main t1 1 \ |
155 UPDATE main t1 3 \ | 187 UPDATE main t1 3 \ |
156 DELETE main t1 1 \ | 188 DELETE main t1 1 \ |
157 DELETE main t1 3 \ | 189 DELETE main t1 3 \ |
158 DELETE main t1 4 \ | 190 DELETE main t1 4 \ |
159 ] | 191 ] |
160 | 192 |
| 193 # EVIDENCE-OF: R-61808-14344 The sqlite3_update_hook() interface does |
| 194 # not fire callbacks for changes to a WITHOUT ROWID table. |
| 195 # |
| 196 # EVIDENCE-OF: R-33257-44249 The update hook is not invoked when WITHOUT |
| 197 # ROWID tables are modified. |
| 198 # |
| 199 do_test hook-4.1.2w { |
| 200 set ::update_hook {} |
| 201 execsql { |
| 202 INSERT INTO t1w VALUES(4, 'four'); |
| 203 DELETE FROM t1w WHERE b = 'two'; |
| 204 UPDATE t1w SET b = '' WHERE a = 1 OR a = 3; |
| 205 DELETE FROM t1w WHERE 1; -- Avoid the truncate optimization (for now) |
| 206 } |
| 207 set ::update_hook |
| 208 } {} |
| 209 |
161 ifcapable trigger { | 210 ifcapable trigger { |
162 # Update hook is not invoked for changes to sqlite_master | 211 # Update hook is not invoked for changes to sqlite_master |
163 # | 212 # |
164 do_test hook-4.1.3 { | 213 do_test hook-4.1.3 { |
165 set ::update_hook {} | 214 set ::update_hook {} |
166 execsql { | 215 execsql { |
167 CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN SELECT RAISE(IGNORE); END; | 216 CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN SELECT RAISE(IGNORE); END; |
168 } | 217 } |
169 set ::update_hook | 218 set ::update_hook |
170 } {} | 219 } {} |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 execsql { | 259 execsql { |
211 INSERT INTO t1 VALUES(1, 'one'); | 260 INSERT INTO t1 VALUES(1, 'one'); |
212 INSERT INTO t1 VALUES(2, 'two'); | 261 INSERT INTO t1 VALUES(2, 'two'); |
213 } | 262 } |
214 } | 263 } |
215 | 264 |
216 # Update-hook + ATTACH | 265 # Update-hook + ATTACH |
217 set ::update_hook {} | 266 set ::update_hook {} |
218 ifcapable attach { | 267 ifcapable attach { |
219 do_test hook-4.2.3 { | 268 do_test hook-4.2.3 { |
220 file delete -force test2.db | 269 forcedelete test2.db |
221 execsql { | 270 execsql { |
222 ATTACH 'test2.db' AS aux; | 271 ATTACH 'test2.db' AS aux; |
223 CREATE TABLE aux.t3(a INTEGER PRIMARY KEY, b); | 272 CREATE TABLE aux.t3(a INTEGER PRIMARY KEY, b); |
224 INSERT INTO aux.t3 SELECT * FROM t1; | 273 INSERT INTO aux.t3 SELECT * FROM t1; |
225 UPDATE t3 SET b = 'two or so' WHERE a = 2; | 274 UPDATE t3 SET b = 'two or so' WHERE a = 2; |
226 DELETE FROM t3 WHERE 1; -- Avoid the truncate optimization (for now) | 275 DELETE FROM t3 WHERE 1; -- Avoid the truncate optimization (for now) |
227 } | 276 } |
228 set ::update_hook | 277 set ::update_hook |
229 } [list \ | 278 } [list \ |
230 INSERT aux t3 1 \ | 279 INSERT aux t3 1 \ |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 SELECT * FROM t1 UNION SELECT * FROM t3; | 316 SELECT * FROM t1 UNION SELECT * FROM t3; |
268 SELECT * FROM t1 UNION ALL SELECT * FROM t3; | 317 SELECT * FROM t1 UNION ALL SELECT * FROM t3; |
269 SELECT * FROM t1 INTERSECT SELECT * FROM t3; | 318 SELECT * FROM t1 INTERSECT SELECT * FROM t3; |
270 SELECT * FROM t1 EXCEPT SELECT * FROM t3; | 319 SELECT * FROM t1 EXCEPT SELECT * FROM t3; |
271 SELECT * FROM t1 ORDER BY b; | 320 SELECT * FROM t1 ORDER BY b; |
272 SELECT * FROM t1 GROUP BY b; | 321 SELECT * FROM t1 GROUP BY b; |
273 } | 322 } |
274 set ::update_hook | 323 set ::update_hook |
275 } [list] | 324 } [list] |
276 } | 325 } |
| 326 |
| 327 do_test hook-4.4 { |
| 328 execsql { |
| 329 CREATE TABLE t4(a UNIQUE, b); |
| 330 INSERT INTO t4 VALUES(1, 'a'); |
| 331 INSERT INTO t4 VALUES(2, 'b'); |
| 332 } |
| 333 set ::update_hook [list] |
| 334 execsql { |
| 335 REPLACE INTO t4 VALUES(1, 'c'); |
| 336 } |
| 337 set ::update_hook |
| 338 } [list INSERT main t4 3 ] |
| 339 do_execsql_test hook-4.4.1 { |
| 340 SELECT * FROM t4 ORDER BY a; |
| 341 } {1 c 2 b} |
| 342 do_test hook-4.4.2 { |
| 343 set ::update_hook [list] |
| 344 execsql { |
| 345 PRAGMA recursive_triggers = on; |
| 346 REPLACE INTO t4 VALUES(1, 'd'); |
| 347 } |
| 348 set ::update_hook |
| 349 } [list INSERT main t4 4 ] |
| 350 do_execsql_test hook-4.4.3 { |
| 351 SELECT * FROM t4 ORDER BY a; |
| 352 } {1 d 2 b} |
| 353 |
277 db update_hook {} | 354 db update_hook {} |
278 # | 355 # |
279 #---------------------------------------------------------------------------- | 356 #---------------------------------------------------------------------------- |
280 | 357 |
281 #---------------------------------------------------------------------------- | 358 #---------------------------------------------------------------------------- |
282 # Test the rollback-hook. The rollback-hook is a bit more complicated than | 359 # Test the rollback-hook. The rollback-hook is a bit more complicated than |
283 # either the commit or update hooks because a rollback can happen | 360 # either the commit or update hooks because a rollback can happen |
284 # explicitly (an sql ROLLBACK statement) or implicitly (a constraint or | 361 # explicitly (an sql ROLLBACK statement) or implicitly (a constraint or |
285 # error condition). | 362 # error condition). |
286 # | 363 # |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 COMMIT; | 432 COMMIT; |
356 } | 433 } |
357 execsql { SELECT * FROM t1 } | 434 execsql { SELECT * FROM t1 } |
358 } {one I} | 435 } {one I} |
359 do_test hook-6.2 { | 436 do_test hook-6.2 { |
360 set ::hooks | 437 set ::hooks |
361 } {COMMIT ROLLBACK} | 438 } {COMMIT ROLLBACK} |
362 unset ::hooks | 439 unset ::hooks |
363 | 440 |
364 finish_test | 441 finish_test |
OLD | NEW |