summaryrefslogtreecommitdiffstats
path: root/test/e_totalchanges.test
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--test/e_totalchanges.test214
1 files changed, 214 insertions, 0 deletions
diff --git a/test/e_totalchanges.test b/test/e_totalchanges.test
new file mode 100644
index 0000000..bb5cfba
--- /dev/null
+++ b/test/e_totalchanges.test
@@ -0,0 +1,214 @@
+# 2011 May 06
+#
+# 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
+set testprefix e_totalchanges
+
+# Like [do_execsql_test], except it appends the value returned by
+# [db total_changes] to the result of executing the SQL script.
+#
+proc do_tc_test {tn sql res} {
+ uplevel [list \
+ do_test $tn "concat \[execsql {$sql}\] \[db total_changes\]" $res
+ ]
+}
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(a, b);
+ CREATE INDEX t1_b ON t1(b);
+ CREATE TABLE t2(x, y, PRIMARY KEY(x, y)) WITHOUT ROWID;
+ CREATE INDEX t2_y ON t2(y);
+}
+
+
+#--------------------------------------------------------------------------
+# EVIDENCE-OF: R-38914-26427 The total_changes() function returns the
+# number of row changes caused by INSERT, UPDATE or DELETE statements
+# since the current database connection was opened.
+#
+# 1.1.*: different types of I/U/D statements,
+# 1.2.*: trigger programs.
+#
+do_tc_test 1.1.1 {
+ INSERT INTO t1 VALUES(1, 2);
+ INSERT INTO t1 VALUES(3, 4);
+ UPDATE t1 SET a = a+1;
+ DELETE FROM t1;
+} {6}
+do_tc_test 1.1.2 {
+ DELETE FROM t1
+} {6}
+
+do_tc_test 1.1.3 {
+ WITH data(a,b) AS (
+ SELECT 0, 0 UNION ALL SELECT a+1, b+1 FROM data WHERE a<99
+ )
+ INSERT INTO t1 SELECT * FROM data;
+} {106}
+
+do_tc_test 1.1.4 {
+ INSERT INTO t2 SELECT * FROM t1 WHERE a<50;
+ UPDATE t2 SET y=y+1;
+} {206}
+
+do_tc_test 1.1.5 {
+ DELETE FROM t2 WHERE y<=25
+} {231}
+
+do_execsql_test 1.2.1 {
+ DELETE FROM t1;
+ DELETE FROM t2;
+}
+sqlite3 db test.db ; # To reset total_changes
+do_tc_test 1.2.2 {
+ CREATE TABLE log(detail);
+ CREATE TRIGGER t1_after_insert AFTER INSERT ON t1 BEGIN
+ INSERT INTO log VALUES('inserted into t1');
+ END;
+
+ CREATE TRIGGER t1_before_delete BEFORE DELETE ON t1 BEGIN
+ INSERT INTO log VALUES('deleting from t1');
+ INSERT INTO log VALUES('here we go!');
+ END;
+
+ CREATE TRIGGER t1_after_update AFTER UPDATE ON t1 BEGIN
+ INSERT INTO log VALUES('update');
+ DELETE FROM log;
+ END;
+
+ INSERT INTO t1 VALUES('a', 'b'); -- 1 + 1
+ UPDATE t1 SET b='c'; -- 1 + 1 + 2
+ DELETE FROM t1; -- 1 + 1 + 1
+} {9}
+
+#--------------------------------------------------------------------------
+# EVIDENCE-OF: R-61766-15253 Executing any other type of SQL statement
+# does not affect the value returned by sqlite3_total_changes().
+ifcapable altertable {
+ do_tc_test 2.1 {
+ INSERT INTO t1 VALUES(1, 2), (3, 4);
+ INSERT INTO t2 VALUES(1, 2), (3, 4);
+ } {15}
+ do_tc_test 2.2 {
+ SELECT count(*) FROM t1;
+ } {2 15}
+ do_tc_test 2.3 {
+ CREATE TABLE t4(a, b);
+ ALTER TABLE t4 ADD COLUMN c;
+ CREATE INDEX i4 ON t4(c);
+ ALTER TABLE t4 RENAME TO t5;
+ ANALYZE;
+ BEGIN;
+ DROP TABLE t2;
+ ROLLBACK;
+ VACUUM;
+ } {15}
+}
+
+
+#--------------------------------------------------------------------------
+# EVIDENCE-OF: R-36043-10590 Changes made as part of foreign key
+# actions are included in the count, but those made as part of REPLACE
+# constraint resolution are not.
+#
+# 3.1.*: foreign key actions
+# 3.2.*: REPLACE constraints.
+#
+sqlite3 db test.db ; # To reset total_changes
+do_tc_test 3.1.1 {
+ CREATE TABLE p1(c PRIMARY KEY, d);
+ CREATE TABLE c1(a, b, FOREIGN KEY(a) REFERENCES p1 ON DELETE SET NULL);
+ CREATE TABLE c2(a, b, FOREIGN KEY(a) REFERENCES p1 ON DELETE CASCADE);
+ CREATE TABLE c3(a, b, FOREIGN KEY(a) REFERENCES p1 ON DELETE SET DEFAULT);
+
+ INSERT INTO p1 VALUES(1, 'one');
+ INSERT INTO p1 VALUES(2, 'two');
+ INSERT INTO p1 VALUES(3, 'three');
+ INSERT INTO p1 VALUES(4, 'four');
+
+ INSERT INTO c1 VALUES(1, 'i');
+ INSERT INTO c2 VALUES(2, 'ii');
+ INSERT INTO c3 VALUES(3, 'iii');
+ PRAGMA foreign_keys = ON;
+} {7}
+
+do_tc_test 3.1.2 { DELETE FROM p1 WHERE c=1; } {9}
+do_tc_test 3.1.3 { DELETE FROM p1 WHERE c=2; } {11}
+do_tc_test 3.1.4 { DELETE FROM p1 WHERE c=3; } {13}
+do_tc_test 3.1.5 { DELETE FROM p1 WHERE c=4; } {14} ; # only 1 this time.
+
+sqlite3 db test.db ; # To reset total_changes
+do_tc_test 3.1.6 {
+ DROP TABLE c1;
+ DROP TABLE c2;
+ DROP TABLE c3;
+ CREATE TABLE c1(a, b, FOREIGN KEY(a) REFERENCES p1 ON UPDATE SET NULL);
+ CREATE TABLE c2(a, b, FOREIGN KEY(a) REFERENCES p1 ON UPDATE CASCADE);
+ CREATE TABLE c3(a, b, FOREIGN KEY(a) REFERENCES p1 ON UPDATE SET DEFAULT);
+
+ INSERT INTO p1 VALUES(1, 'one');
+ INSERT INTO p1 VALUES(2, 'two');
+ INSERT INTO p1 VALUES(3, 'three');
+ INSERT INTO p1 VALUES(4, 'four');
+
+ INSERT INTO c1 VALUES(1, 'i');
+ INSERT INTO c2 VALUES(2, 'ii');
+ INSERT INTO c3 VALUES(3, 'iii');
+ PRAGMA foreign_keys = ON;
+} {7}
+
+do_tc_test 3.1.7 { UPDATE p1 SET c=c+4 WHERE c=1; } {9}
+do_tc_test 3.1.8 { UPDATE p1 SET c=c+4 WHERE c=2; } {11}
+do_tc_test 3.1.9 { UPDATE p1 SET c=c+4 WHERE c=3; } {13}
+do_tc_test 3.1.10 { UPDATE p1 SET c=c+4 WHERE c=4; } {14} ; # only 1 this time.
+
+sqlite3 db test.db ; # To reset total_changes
+do_tc_test 3.2.1 {
+ CREATE TABLE t3(a UNIQUE, b UNIQUE);
+ INSERT INTO t3 VALUES('one', 'one');
+ INSERT INTO t3 VALUES('two', 'two');
+ INSERT OR REPLACE INTO t3 VALUES('one', 'two');
+} {3}
+
+do_tc_test 3.2.2 {
+ INSERT INTO t3 VALUES('three', 'one');
+ UPDATE OR REPLACE t3 SET b='two' WHERE b='one';
+ SELECT * FROM t3;
+} {three two 5}
+
+#--------------------------------------------------------------------------
+# EVIDENCE-OF: R-54872-08741 Changes to a view that are intercepted by
+# INSTEAD OF triggers are not counted.
+#
+sqlite3 db test.db ; # To reset total_changes
+do_tc_test 4.1 {
+ CREATE TABLE t6(x);
+ CREATE VIEW v1 AS SELECT * FROM t6;
+ CREATE TRIGGER v1_tr1 INSTEAD OF INSERT ON v1 BEGIN
+ SELECT 'no-op';
+ END;
+
+ INSERT INTO v1 VALUES('a');
+ INSERT INTO v1 VALUES('b');
+} {0}
+do_tc_test 4.2 {
+ CREATE TRIGGER v1_tr2 INSTEAD OF INSERT ON v1 BEGIN
+ INSERT INTO t6 VALUES(new.x);
+ END;
+
+ INSERT INTO v1 VALUES('c');
+ INSERT INTO v1 VALUES('d');
+} {2}
+
+
+finish_test