xref: /sqlite-3.40.0/test/e_totalchanges.test (revision 37f3ac8f)
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
13set testdir [file dirname $argv0]
14source $testdir/tester.tcl
15set 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#
20proc do_tc_test {tn sql res} {
21  uplevel [list \
22    do_test $tn "concat \[execsql {$sql}\] \[db total_changes\]" $res
23  ]
24}
25
26do_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-38914-26427 The total_changes() function returns the
36# number of row changes caused by INSERT, UPDATE or DELETE statements
37# since the current database connection was opened.
38#
39#   1.1.*: different types of I/U/D statements,
40#   1.2.*: trigger programs.
41#
42do_tc_test 1.1.1 {
43  INSERT INTO t1 VALUES(1, 2);
44  INSERT INTO t1 VALUES(3, 4);
45  UPDATE t1 SET a = a+1;
46  DELETE FROM t1;
47} {6}
48do_tc_test 1.1.2 {
49  DELETE FROM t1
50} {6}
51
52do_tc_test 1.1.3 {
53  WITH data(a,b) AS (
54      SELECT 0, 0 UNION ALL SELECT a+1, b+1 FROM data WHERE a<99
55  )
56  INSERT INTO t1 SELECT * FROM data;
57} {106}
58
59do_tc_test 1.1.4 {
60  INSERT INTO t2 SELECT * FROM t1 WHERE a<50;
61  UPDATE t2 SET y=y+1;
62} {206}
63
64do_tc_test 1.1.5 {
65  DELETE FROM t2 WHERE y<=25
66} {231}
67
68do_execsql_test 1.2.1 {
69  DELETE FROM t1;
70  DELETE FROM t2;
71}
72sqlite3 db test.db     ; # To reset total_changes
73do_tc_test 1.2.2 {
74  CREATE TABLE log(detail);
75  CREATE TRIGGER t1_after_insert AFTER INSERT ON t1 BEGIN
76    INSERT INTO log VALUES('inserted into t1');
77  END;
78
79  CREATE TRIGGER t1_before_delete BEFORE DELETE ON t1 BEGIN
80    INSERT INTO log VALUES('deleting from t1');
81    INSERT INTO log VALUES('here we go!');
82  END;
83
84  CREATE TRIGGER t1_after_update AFTER UPDATE ON t1 BEGIN
85    INSERT INTO log VALUES('update');
86    DELETE FROM log;
87  END;
88
89  INSERT INTO t1 VALUES('a', 'b');   -- 1 + 1
90  UPDATE t1 SET b='c';               -- 1 + 1 + 2
91  DELETE FROM t1;                    -- 1 + 1 + 1
92} {9}
93
94#--------------------------------------------------------------------------
95# EVIDENCE-OF: R-61766-15253 Executing any other type of SQL statement
96# does not affect the value returned by sqlite3_total_changes().
97ifcapable altertable {
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#--------------------------------------------------------------------------
120# EVIDENCE-OF: R-36043-10590 Changes made as part of foreign key
121# actions are included in the count, but those made as part of REPLACE
122# constraint resolution are not.
123#
124#   3.1.*: foreign key actions
125#   3.2.*: REPLACE constraints.
126#
127sqlite3 db test.db     ; # To reset total_changes
128do_tc_test 3.1.1 {
129  CREATE TABLE p1(c PRIMARY KEY, d);
130  CREATE TABLE c1(a, b, FOREIGN KEY(a) REFERENCES p1 ON DELETE SET NULL);
131  CREATE TABLE c2(a, b, FOREIGN KEY(a) REFERENCES p1 ON DELETE CASCADE);
132  CREATE TABLE c3(a, b, FOREIGN KEY(a) REFERENCES p1 ON DELETE SET DEFAULT);
133
134  INSERT INTO p1 VALUES(1, 'one');
135  INSERT INTO p1 VALUES(2, 'two');
136  INSERT INTO p1 VALUES(3, 'three');
137  INSERT INTO p1 VALUES(4, 'four');
138
139  INSERT INTO c1 VALUES(1, 'i');
140  INSERT INTO c2 VALUES(2, 'ii');
141  INSERT INTO c3 VALUES(3, 'iii');
142  PRAGMA foreign_keys = ON;
143} {7}
144
145do_tc_test 3.1.2 { DELETE FROM p1 WHERE c=1; } {9}
146do_tc_test 3.1.3 { DELETE FROM p1 WHERE c=2; } {11}
147do_tc_test 3.1.4 { DELETE FROM p1 WHERE c=3; } {13}
148do_tc_test 3.1.5 { DELETE FROM p1 WHERE c=4; } {14}  ; # only 1 this time.
149
150sqlite3 db test.db     ; # To reset total_changes
151do_tc_test 3.1.6 {
152  DROP TABLE c1;
153  DROP TABLE c2;
154  DROP TABLE c3;
155  CREATE TABLE c1(a, b, FOREIGN KEY(a) REFERENCES p1 ON UPDATE SET NULL);
156  CREATE TABLE c2(a, b, FOREIGN KEY(a) REFERENCES p1 ON UPDATE CASCADE);
157  CREATE TABLE c3(a, b, FOREIGN KEY(a) REFERENCES p1 ON UPDATE SET DEFAULT);
158
159  INSERT INTO p1 VALUES(1, 'one');
160  INSERT INTO p1 VALUES(2, 'two');
161  INSERT INTO p1 VALUES(3, 'three');
162  INSERT INTO p1 VALUES(4, 'four');
163
164  INSERT INTO c1 VALUES(1, 'i');
165  INSERT INTO c2 VALUES(2, 'ii');
166  INSERT INTO c3 VALUES(3, 'iii');
167  PRAGMA foreign_keys = ON;
168} {7}
169
170do_tc_test 3.1.7  { UPDATE p1 SET c=c+4 WHERE c=1; } {9}
171do_tc_test 3.1.8  { UPDATE p1 SET c=c+4 WHERE c=2; } {11}
172do_tc_test 3.1.9  { UPDATE p1 SET c=c+4 WHERE c=3; } {13}
173do_tc_test 3.1.10 { UPDATE p1 SET c=c+4 WHERE c=4; } {14}  ; # only 1 this time.
174
175sqlite3 db test.db     ; # To reset total_changes
176do_tc_test 3.2.1 {
177  CREATE TABLE t3(a UNIQUE, b UNIQUE);
178  INSERT INTO t3 VALUES('one', 'one');
179  INSERT INTO t3 VALUES('two', 'two');
180  INSERT OR REPLACE INTO t3 VALUES('one', 'two');
181} {3}
182
183do_tc_test 3.2.2 {
184  INSERT INTO t3 VALUES('three', 'one');
185  UPDATE OR REPLACE t3 SET b='two' WHERE b='one';
186  SELECT * FROM t3;
187} {three two 5}
188
189#--------------------------------------------------------------------------
190# EVIDENCE-OF: R-54872-08741 Changes to a view that are intercepted by
191# INSTEAD OF triggers are not counted.
192#
193sqlite3 db test.db     ; # To reset total_changes
194do_tc_test 4.1 {
195  CREATE TABLE t6(x);
196  CREATE VIEW v1 AS SELECT * FROM t6;
197  CREATE TRIGGER v1_tr1 INSTEAD OF INSERT ON v1 BEGIN
198    SELECT 'no-op';
199  END;
200
201  INSERT INTO v1 VALUES('a');
202  INSERT INTO v1 VALUES('b');
203} {0}
204do_tc_test 4.2 {
205  CREATE TRIGGER v1_tr2 INSTEAD OF INSERT ON v1 BEGIN
206    INSERT INTO t6 VALUES(new.x);
207  END;
208
209  INSERT INTO v1 VALUES('c');
210  INSERT INTO v1 VALUES('d');
211} {2}
212
213
214finish_test
215