blob: 6e31d1af972f456150f986135427953ec12a8da7 [file] [log] [blame]
danielk19778f2c54e2008-01-01 19:02:09 +00001# 2008 January 1
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# This file implements regression tests for SQLite library. Specifically,
12# it tests some compiler optimizations for SQL statements featuring
13# triggers:
14#
15#
16#
17
18# trigger9-1.* - Test that if there are no references to OLD.* cols, or a
19# reference to only OLD.rowid, the data is not loaded.
20#
21# trigger9-2.* - Test that for NEW.* records populated by UPDATE
22# statements, unused fields are populated with NULL values.
23#
24# trigger9-3.* - Test that the temporary tables used for OLD.* references
25# in "INSTEAD OF" triggers have NULL values in unused
26# fields.
27#
28
29set testdir [file dirname $argv0]
30source $testdir/tester.tcl
31ifcapable {!trigger} {
32 finish_test
33 return
34}
dandd8c4602014-10-28 16:50:10 +000035set ::testprefix trigger9
danielk19778f2c54e2008-01-01 19:02:09 +000036
37proc has_rowdata {sql} {
38 expr {[lsearch [execsql "explain $sql"] RowData]>=0}
39}
40
41do_test trigger9-1.1 {
42 execsql {
43 PRAGMA page_size = 1024;
44 CREATE TABLE t1(x, y, z);
45 INSERT INTO t1 VALUES('1', randstr(10000,10000), '2');
46 INSERT INTO t1 VALUES('2', randstr(10000,10000), '4');
47 INSERT INTO t1 VALUES('3', randstr(10000,10000), '6');
48 CREATE TABLE t2(x);
49 }
50} {}
51
52do_test trigger9-1.2.1 {
danielk19778f2c54e2008-01-01 19:02:09 +000053 execsql {
54 BEGIN;
55 CREATE TRIGGER trig1 BEFORE DELETE ON t1 BEGIN
56 INSERT INTO t2 VALUES(old.rowid);
57 END;
58 DELETE FROM t1;
59 SELECT * FROM t2;
60 }
61} {1 2 3}
62do_test trigger9-1.2.3 {
63 has_rowdata {DELETE FROM t1}
64} 0
65do_test trigger9-1.2.4 { execsql { ROLLBACK } } {}
66
67do_test trigger9-1.3.1 {
danielk19778f2c54e2008-01-01 19:02:09 +000068 execsql {
69 BEGIN;
70 CREATE TRIGGER trig1 BEFORE DELETE ON t1 BEGIN
71 INSERT INTO t2 VALUES(old.x);
72 END;
73 DELETE FROM t1;
74 SELECT * FROM t2;
75 }
76} {1 2 3}
77do_test trigger9-1.3.2 {
78 has_rowdata {DELETE FROM t1}
dan76d462e2009-08-30 11:42:51 +000079} 0
danielk19778f2c54e2008-01-01 19:02:09 +000080do_test trigger9-1.3.3 { execsql { ROLLBACK } } {}
81
82do_test trigger9-1.4.1 {
danielk19778f2c54e2008-01-01 19:02:09 +000083 execsql {
84 BEGIN;
85 CREATE TRIGGER trig1 BEFORE DELETE ON t1 WHEN old.x='1' BEGIN
86 INSERT INTO t2 VALUES(old.rowid);
87 END;
88 DELETE FROM t1;
89 SELECT * FROM t2;
90 }
91} {1}
92do_test trigger9-1.4.2 {
93 has_rowdata {DELETE FROM t1}
dan76d462e2009-08-30 11:42:51 +000094} 0
danielk19778f2c54e2008-01-01 19:02:09 +000095do_test trigger9-1.4.3 { execsql { ROLLBACK } } {}
96
97do_test trigger9-1.5.1 {
danielk19778f2c54e2008-01-01 19:02:09 +000098 execsql {
99 BEGIN;
100 CREATE TRIGGER trig1 BEFORE UPDATE ON t1 BEGIN
101 INSERT INTO t2 VALUES(old.rowid);
102 END;
103 UPDATE t1 SET y = '';
104 SELECT * FROM t2;
105 }
106} {1 2 3}
107do_test trigger9-1.5.2 {
108 has_rowdata {UPDATE t1 SET y = ''}
109} 0
110do_test trigger9-1.5.3 { execsql { ROLLBACK } } {}
111
112do_test trigger9-1.6.1 {
danielk19778f2c54e2008-01-01 19:02:09 +0000113 execsql {
114 BEGIN;
115 CREATE TRIGGER trig1 BEFORE UPDATE ON t1 BEGIN
116 INSERT INTO t2 VALUES(old.x);
117 END;
118 UPDATE t1 SET y = '';
119 SELECT * FROM t2;
120 }
121} {1 2 3}
122do_test trigger9-1.6.2 {
123 has_rowdata {UPDATE t1 SET y = ''}
dan76d462e2009-08-30 11:42:51 +0000124} 0
danielk19778f2c54e2008-01-01 19:02:09 +0000125do_test trigger9-1.6.3 { execsql { ROLLBACK } } {}
126
127do_test trigger9-1.7.1 {
danielk19778f2c54e2008-01-01 19:02:09 +0000128 execsql {
129 BEGIN;
130 CREATE TRIGGER trig1 BEFORE UPDATE ON t1 WHEN old.x>='2' BEGIN
131 INSERT INTO t2 VALUES(old.x);
132 END;
133 UPDATE t1 SET y = '';
134 SELECT * FROM t2;
135 }
136} {2 3}
137do_test trigger9-1.7.2 {
138 has_rowdata {UPDATE t1 SET y = ''}
dan76d462e2009-08-30 11:42:51 +0000139} 0
danielk19778f2c54e2008-01-01 19:02:09 +0000140do_test trigger9-1.7.3 { execsql { ROLLBACK } } {}
141
danielk1977eb9ae902008-01-02 04:41:24 +0000142do_test trigger9-3.1 {
143 execsql {
144 CREATE TABLE t3(a, b);
145 INSERT INTO t3 VALUES(1, 'one');
146 INSERT INTO t3 VALUES(2, 'two');
147 INSERT INTO t3 VALUES(3, 'three');
148 }
149} {}
150do_test trigger9-3.2 {
151 execsql {
152 BEGIN;
153 CREATE VIEW v1 AS SELECT * FROM t3;
154 CREATE TRIGGER trig1 INSTEAD OF UPDATE ON v1 BEGIN
155 INSERT INTO t2 VALUES(old.a);
156 END;
157 UPDATE v1 SET b = 'hello';
158 SELECT * FROM t2;
159 ROLLBACK;
160 }
161} {1 2 3}
162do_test trigger9-3.3 {
163 # In this test the 'c' column of the view is not required by
164 # the INSTEAD OF trigger, but the expression is reused internally as
165 # part of the view's WHERE clause. Check that this does not cause
166 # a problem.
167 #
168 execsql {
169 BEGIN;
170 CREATE VIEW v1 AS SELECT a, b AS c FROM t3 WHERE c > 'one';
171 CREATE TRIGGER trig1 INSTEAD OF UPDATE ON v1 BEGIN
172 INSERT INTO t2 VALUES(old.a);
173 END;
174 UPDATE v1 SET c = 'hello';
175 SELECT * FROM t2;
176 ROLLBACK;
177 }
178} {2 3}
179do_test trigger9-3.4 {
180 execsql {
181 BEGIN;
182 INSERT INTO t3 VALUES(3, 'three');
183 INSERT INTO t3 VALUES(3, 'four');
184 CREATE VIEW v1 AS SELECT DISTINCT a, b FROM t3;
185 CREATE TRIGGER trig1 INSTEAD OF UPDATE ON v1 BEGIN
186 INSERT INTO t2 VALUES(old.a);
187 END;
188 UPDATE v1 SET b = 'hello';
189 SELECT * FROM t2;
190 ROLLBACK;
191 }
192} {1 2 3 3}
danielk1977de3e41e2008-08-04 03:51:24 +0000193
194ifcapable compound {
195 do_test trigger9-3.5 {
196 execsql {
197 BEGIN;
198 INSERT INTO t3 VALUES(1, 'uno');
199 CREATE VIEW v1 AS SELECT a, b FROM t3 EXCEPT SELECT 1, 'one';
200 CREATE TRIGGER trig1 INSTEAD OF UPDATE ON v1 BEGIN
201 INSERT INTO t2 VALUES(old.a);
202 END;
203 UPDATE v1 SET b = 'hello';
204 SELECT * FROM t2;
205 ROLLBACK;
206 }
207 } {1 2 3}
208 do_test trigger9-3.6 {
209 execsql {
210 BEGIN;
211 INSERT INTO t3 VALUES(1, 'zero');
212 CREATE VIEW v1 AS
213 SELECT sum(a) AS a, max(b) AS b FROM t3 GROUP BY t3.a HAVING b>'two';
214 CREATE TRIGGER trig1 INSTEAD OF UPDATE ON v1 BEGIN
215 INSERT INTO t2 VALUES(old.a);
216 END;
217 UPDATE v1 SET b = 'hello';
218 SELECT * FROM t2;
219 ROLLBACK;
220 }
221 } {2}
222}
danielk1977eb9ae902008-01-02 04:41:24 +0000223
dandd8c4602014-10-28 16:50:10 +0000224reset_db
225do_execsql_test 4.1 {
226 CREATE TABLE t1(a, b);
227 CREATE TABLE log(x);
228 INSERT INTO t1 VALUES(1, 2);
229 INSERT INTO t1 VALUES(3, 4);
230 CREATE VIEW v1 AS SELECT a, b FROM t1;
231
232 CREATE TRIGGER tr1 INSTEAD OF DELETE ON v1 BEGIN
233 INSERT INTO log VALUES('delete');
234 END;
235
236 CREATE TRIGGER tr2 INSTEAD OF UPDATE ON v1 BEGIN
237 INSERT INTO log VALUES('update');
238 END;
239
240 CREATE TRIGGER tr3 INSTEAD OF INSERT ON v1 BEGIN
241 INSERT INTO log VALUES('insert');
242 END;
243}
244
drha6c54de2021-04-06 19:13:44 +0000245do_catchsql_test 4.2 {
dandd8c4602014-10-28 16:50:10 +0000246 DELETE FROM v1 WHERE rowid=1;
drha6c54de2021-04-06 19:13:44 +0000247} {1 {no such column: rowid}}
dandd8c4602014-10-28 16:50:10 +0000248
drha6c54de2021-04-06 19:13:44 +0000249do_catchsql_test 4.3 {
dandd8c4602014-10-28 16:50:10 +0000250 UPDATE v1 SET a=b WHERE rowid=2;
drha6c54de2021-04-06 19:13:44 +0000251} {1 {no such column: rowid}}
dandd8c4602014-10-28 16:50:10 +0000252
danielk19778f2c54e2008-01-01 19:02:09 +0000253finish_test