OLD | NEW |
(Empty) | |
| 1 # 2011 May 06 |
| 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 set testprefix e_totalchanges |
| 16 |
| 17 # Like [do_execsql_test], except it appends the value returned by |
| 18 # [db total_changes] to the result of executing the SQL script. |
| 19 # |
| 20 proc do_tc_test {tn sql res} { |
| 21 uplevel [list \ |
| 22 do_test $tn "concat \[execsql {$sql}\] \[db total_changes\]" $res |
| 23 ] |
| 24 } |
| 25 |
| 26 do_execsql_test 1.0 { |
| 27 CREATE TABLE t1(a, b); |
| 28 CREATE INDEX t1_b ON t1(b); |
| 29 CREATE TABLE t2(x, y, PRIMARY KEY(x, y)) WITHOUT ROWID; |
| 30 CREATE INDEX t2_y ON t2(y); |
| 31 } |
| 32 |
| 33 |
| 34 #-------------------------------------------------------------------------- |
| 35 # EVIDENCE-OF: R-65438-26258 This function returns the total number of |
| 36 # rows inserted, modified or deleted by all INSERT, UPDATE or DELETE |
| 37 # statements completed since the database connection was opened, |
| 38 # including those executed as part of trigger programs. |
| 39 # |
| 40 # 1.1.*: different types of I/U/D statements, |
| 41 # 1.2.*: trigger programs. |
| 42 # |
| 43 do_tc_test 1.1.1 { |
| 44 INSERT INTO t1 VALUES(1, 2); |
| 45 INSERT INTO t1 VALUES(3, 4); |
| 46 UPDATE t1 SET a = a+1; |
| 47 DELETE FROM t1; |
| 48 } {6} |
| 49 do_tc_test 1.1.2 { |
| 50 DELETE FROM t1 |
| 51 } {6} |
| 52 |
| 53 do_tc_test 1.1.3 { |
| 54 WITH data(a,b) AS ( |
| 55 SELECT 0, 0 UNION ALL SELECT a+1, b+1 FROM data WHERE a<99 |
| 56 ) |
| 57 INSERT INTO t1 SELECT * FROM data; |
| 58 } {106} |
| 59 |
| 60 do_tc_test 1.1.4 { |
| 61 INSERT INTO t2 SELECT * FROM t1 WHERE a<50; |
| 62 UPDATE t2 SET y=y+1; |
| 63 } {206} |
| 64 |
| 65 do_tc_test 1.1.5 { |
| 66 DELETE FROM t2 WHERE y<=25 |
| 67 } {231} |
| 68 |
| 69 do_execsql_test 1.2.1 { |
| 70 DELETE FROM t1; |
| 71 DELETE FROM t2; |
| 72 } |
| 73 sqlite3 db test.db ; # To reset total_changes |
| 74 do_tc_test 1.2.2 { |
| 75 CREATE TABLE log(detail); |
| 76 CREATE TRIGGER t1_after_insert AFTER INSERT ON t1 BEGIN |
| 77 INSERT INTO log VALUES('inserted into t1'); |
| 78 END; |
| 79 |
| 80 CREATE TRIGGER t1_before_delete BEFORE DELETE ON t1 BEGIN |
| 81 INSERT INTO log VALUES('deleting from t1'); |
| 82 INSERT INTO log VALUES('here we go!'); |
| 83 END; |
| 84 |
| 85 CREATE TRIGGER t1_after_update AFTER UPDATE ON t1 BEGIN |
| 86 INSERT INTO log VALUES('update'); |
| 87 DELETE FROM log; |
| 88 END; |
| 89 |
| 90 INSERT INTO t1 VALUES('a', 'b'); -- 1 + 1 |
| 91 UPDATE t1 SET b='c'; -- 1 + 1 + 2 |
| 92 DELETE FROM t1; -- 1 + 1 + 1 |
| 93 } {9} |
| 94 |
| 95 #-------------------------------------------------------------------------- |
| 96 # EVIDENCE-OF: R-61766-15253 Executing any other type of SQL statement |
| 97 # does not affect the value returned by sqlite3_total_changes(). |
| 98 do_tc_test 2.1 { |
| 99 INSERT INTO t1 VALUES(1, 2), (3, 4); |
| 100 INSERT INTO t2 VALUES(1, 2), (3, 4); |
| 101 } {15} |
| 102 do_tc_test 2.2 { |
| 103 SELECT count(*) FROM t1; |
| 104 } {2 15} |
| 105 do_tc_test 2.3 { |
| 106 CREATE TABLE t4(a, b); |
| 107 ALTER TABLE t4 ADD COLUMN c; |
| 108 CREATE INDEX i4 ON t4(c); |
| 109 ALTER TABLE t4 RENAME TO t5; |
| 110 ANALYZE; |
| 111 BEGIN; |
| 112 DROP TABLE t2; |
| 113 ROLLBACK; |
| 114 VACUUM; |
| 115 } {15} |
| 116 |
| 117 |
| 118 #-------------------------------------------------------------------------- |
| 119 # EVIDENCE-OF: R-36043-10590 Changes made as part of foreign key |
| 120 # actions are included in the count, but those made as part of REPLACE |
| 121 # constraint resolution are not. |
| 122 # |
| 123 # 3.1.*: foreign key actions |
| 124 # 3.2.*: REPLACE constraints. |
| 125 # |
| 126 sqlite3 db test.db ; # To reset total_changes |
| 127 do_tc_test 3.1.1 { |
| 128 CREATE TABLE p1(c PRIMARY KEY, d); |
| 129 CREATE TABLE c1(a, b, FOREIGN KEY(a) REFERENCES p1 ON DELETE SET NULL); |
| 130 CREATE TABLE c2(a, b, FOREIGN KEY(a) REFERENCES p1 ON DELETE CASCADE); |
| 131 CREATE TABLE c3(a, b, FOREIGN KEY(a) REFERENCES p1 ON DELETE SET DEFAULT); |
| 132 |
| 133 INSERT INTO p1 VALUES(1, 'one'); |
| 134 INSERT INTO p1 VALUES(2, 'two'); |
| 135 INSERT INTO p1 VALUES(3, 'three'); |
| 136 INSERT INTO p1 VALUES(4, 'four'); |
| 137 |
| 138 INSERT INTO c1 VALUES(1, 'i'); |
| 139 INSERT INTO c2 VALUES(2, 'ii'); |
| 140 INSERT INTO c3 VALUES(3, 'iii'); |
| 141 PRAGMA foreign_keys = ON; |
| 142 } {7} |
| 143 |
| 144 do_tc_test 3.1.2 { DELETE FROM p1 WHERE c=1; } {9} |
| 145 do_tc_test 3.1.3 { DELETE FROM p1 WHERE c=2; } {11} |
| 146 do_tc_test 3.1.4 { DELETE FROM p1 WHERE c=3; } {13} |
| 147 do_tc_test 3.1.5 { DELETE FROM p1 WHERE c=4; } {14} ; # only 1 this time. |
| 148 |
| 149 sqlite3 db test.db ; # To reset total_changes |
| 150 do_tc_test 3.1.6 { |
| 151 DROP TABLE c1; |
| 152 DROP TABLE c2; |
| 153 DROP TABLE c3; |
| 154 CREATE TABLE c1(a, b, FOREIGN KEY(a) REFERENCES p1 ON UPDATE SET NULL); |
| 155 CREATE TABLE c2(a, b, FOREIGN KEY(a) REFERENCES p1 ON UPDATE CASCADE); |
| 156 CREATE TABLE c3(a, b, FOREIGN KEY(a) REFERENCES p1 ON UPDATE SET DEFAULT); |
| 157 |
| 158 INSERT INTO p1 VALUES(1, 'one'); |
| 159 INSERT INTO p1 VALUES(2, 'two'); |
| 160 INSERT INTO p1 VALUES(3, 'three'); |
| 161 INSERT INTO p1 VALUES(4, 'four'); |
| 162 |
| 163 INSERT INTO c1 VALUES(1, 'i'); |
| 164 INSERT INTO c2 VALUES(2, 'ii'); |
| 165 INSERT INTO c3 VALUES(3, 'iii'); |
| 166 PRAGMA foreign_keys = ON; |
| 167 } {7} |
| 168 |
| 169 do_tc_test 3.1.7 { UPDATE p1 SET c=c+4 WHERE c=1; } {9} |
| 170 do_tc_test 3.1.8 { UPDATE p1 SET c=c+4 WHERE c=2; } {11} |
| 171 do_tc_test 3.1.9 { UPDATE p1 SET c=c+4 WHERE c=3; } {13} |
| 172 do_tc_test 3.1.10 { UPDATE p1 SET c=c+4 WHERE c=4; } {14} ; # only 1 this time. |
| 173 |
| 174 sqlite3 db test.db ; # To reset total_changes |
| 175 do_tc_test 3.2.1 { |
| 176 CREATE TABLE t3(a UNIQUE, b UNIQUE); |
| 177 INSERT INTO t3 VALUES('one', 'one'); |
| 178 INSERT INTO t3 VALUES('two', 'two'); |
| 179 INSERT OR REPLACE INTO t3 VALUES('one', 'two'); |
| 180 } {3} |
| 181 |
| 182 do_tc_test 3.2.2 { |
| 183 INSERT INTO t3 VALUES('three', 'one'); |
| 184 UPDATE OR REPLACE t3 SET b='two' WHERE b='one'; |
| 185 SELECT * FROM t3; |
| 186 } {three two 5} |
| 187 |
| 188 #-------------------------------------------------------------------------- |
| 189 # EVIDENCE-OF: R-54872-08741 Changes to a view that are intercepted by |
| 190 # INSTEAD OF triggers are not counted. |
| 191 # |
| 192 sqlite3 db test.db ; # To reset total_changes |
| 193 do_tc_test 4.1 { |
| 194 CREATE TABLE t6(x); |
| 195 CREATE VIEW v1 AS SELECT * FROM t6; |
| 196 CREATE TRIGGER v1_tr1 INSTEAD OF INSERT ON v1 BEGIN |
| 197 SELECT 'no-op'; |
| 198 END; |
| 199 |
| 200 INSERT INTO v1 VALUES('a'); |
| 201 INSERT INTO v1 VALUES('b'); |
| 202 } {0} |
| 203 do_tc_test 4.2 { |
| 204 CREATE TRIGGER v1_tr2 INSTEAD OF INSERT ON v1 BEGIN |
| 205 INSERT INTO t6 VALUES(new.x); |
| 206 END; |
| 207 |
| 208 INSERT INTO v1 VALUES('c'); |
| 209 INSERT INTO v1 VALUES('d'); |
| 210 } {2} |
| 211 |
| 212 |
| 213 finish_test |
OLD | NEW |