3 # The author disclaims copyright to this source code. In place of
4 # a legal notice, here is a blessing:
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.
10 #***********************************************************************
13 set testdir [file dirname $argv0]
14 source $testdir/tester.tcl
15 set testprefix upfrom2
19 # 1.*: Test that triggers are fired correctly for UPDATE FROM statements,
20 # and only once for each row. Except for INSTEAD OF triggers on
21 # views - these are fired once for each row returned by the join,
22 # including duplicates.
24 # 2.*: Test adding ORDER BY and LIMIT clauses with UPDATE FROM statements.
26 # 5.*: Test that specifying the target table name or alias in the FROM
27 # clause of an UPDATE statement is an error.
36 eval [string map [list %WO% $wo %TN% $tn] {
37 do_execsql_test 1.%TN%.0 {
38 CREATE TABLE log(t TEXT);
39 CREATE TABLE t1(x PRIMARY KEY, y, z UNIQUE) %WO%;
40 CREATE INDEX t1y ON t1(y);
42 INSERT INTO t1 VALUES(1, 'i', 'one');
43 INSERT INTO t1 VALUES(2, 'ii', 'two');
44 INSERT INTO t1 VALUES(3, 'iii', 'three');
45 INSERT INTO t1 VALUES(4, 'iv', 'four');
47 CREATE TRIGGER tr1 BEFORE UPDATE ON t1 BEGIN
48 INSERT INTO log VALUES(old.z || '->' || new.z);
50 CREATE TRIGGER tr2 AFTER UPDATE ON t1 BEGIN
51 INSERT INTO log VALUES(old.y || '->' || new.y);
55 do_execsql_test 1.%TN%.1 {
57 VALUES(3, 'thirty'), (1, 'ten')
59 UPDATE t1 SET z=v FROM data WHERE x=k;
64 1 i ten 2 ii two 3 iii thirty 4 iv four
66 three->thirty iii->iii
69 do_execsql_test 1.%TN%.2 {
70 CREATE TABLE t2(a, b);
71 CREATE TABLE t3(k, v);
73 INSERT INTO t3 VALUES(5, 'v');
74 INSERT INTO t3 VALUES(12, 'xii');
76 INSERT INTO t2 VALUES(2, 12);
77 INSERT INTO t2 VALUES(3, 5);
80 UPDATE t1 SET y=v FROM t2, t3 WHERE t1.x=t2.a AND t3.k=t2.b;
85 1 i ten 2 xii two 3 v thirty 4 iv four
90 do_execsql_test 1.%TN%.3 {
93 VALUES(1, 'seven'), (1, 'eight'), (2, 'eleven'), (2, 'twelve')
95 UPDATE t1 SET z=v FROM data WHERE x=k;
100 1 i eight 2 xii twelve 3 v thirty 4 iv four
105 do_test 1.%TN%.4 { db changes } {2}
107 do_execsql_test 1.%TN%.5 {
108 CREATE VIEW v1 AS SELECT * FROM t1;
109 CREATE TRIGGER v1tr INSTEAD OF UPDATE ON v1 BEGIN
110 UPDATE t1 SET y=new.y, z=new.z WHERE x=new.x;
115 VALUES(3, 'thirteen'), (3, 'fourteen'), (4, 'fifteen'), (4, 'sixteen')
117 UPDATE v1 SET z=v FROM data WHERE x=k;
120 do_execsql_test 1.%TN%.6 {
124 1 i eight 2 xii twelve 3 v fourteen 4 iv sixteen
125 thirty->thirteen v->v
126 thirteen->fourteen v->v
128 fifteen->sixteen iv->iv
131 #--------------------------------------------------------------
133 do_execsql_test 1.%TN%.7 {
134 CREATE TABLE o1(w, x, y, z UNIQUE, PRIMARY KEY(w, x)) %WO%;
135 CREATE INDEX o1y ON t1(y);
137 INSERT INTO o1 VALUES(0, 0, 'i', 'one');
138 INSERT INTO o1 VALUES(0, 1, 'ii', 'two');
139 INSERT INTO o1 VALUES(1, 0, 'iii', 'three');
140 INSERT INTO o1 VALUES(1, 1, 'iv', 'four');
142 CREATE TRIGGER tro1 BEFORE UPDATE ON o1 BEGIN
143 INSERT INTO log VALUES(old.z || '->' || new.z);
145 CREATE TRIGGER tro2 AFTER UPDATE ON o1 BEGIN
146 INSERT INTO log VALUES(old.y || '->' || new.y);
150 do_execsql_test 1.%TN%.8 {
153 VALUES(3, 'thirty'), (1, 'ten')
155 UPDATE o1 SET z=v FROM data WHERE (1+x+w*2)=k;
160 0 0 i ten 0 1 ii two 1 0 iii thirty 1 1 iv four
162 three->thirty iii->iii
165 do_execsql_test 1.%TN%.9 {
167 UPDATE o1 SET y=v FROM t2, t3 WHERE (1+o1.w*2+o1.x)=t2.a AND t3.k=t2.b;
172 0 0 i ten 0 1 xii two 1 0 v thirty 1 1 iv four
174 thirty->thirty iii->v
177 do_execsql_test 1.%TN%.10 {
180 VALUES(1, 'seven'), (1, 'eight'), (2, 'eleven'), (2, 'twelve')
182 UPDATE o1 SET z=v FROM data WHERE (1+w*2+x)=k;
187 0 0 i eight 0 1 xii twelve 1 0 v thirty 1 1 iv four
192 do_test 1.%TN%.11 { db changes } {2}
194 do_execsql_test 1.%TN%.12 {
195 CREATE VIEW w1 AS SELECT * FROM o1;
196 CREATE TRIGGER w1tr INSTEAD OF UPDATE ON w1 BEGIN
197 UPDATE o1 SET y=new.y, z=new.z WHERE w=new.w AND x=new.x;
202 VALUES(3, 'thirteen'), (3, 'fourteen'), (4, 'fifteen'), (4, 'sixteen')
204 UPDATE w1 SET z=v FROM data WHERE (1+w*2+x)=k;
207 do_execsql_test 1.%TN%.13 {
211 0 0 i eight 0 1 xii twelve 1 0 v fourteen 1 1 iv sixteen
212 thirty->thirteen v->v
213 thirteen->fourteen v->v
215 fifteen->sixteen iv->iv
221 ifcapable update_delete_limit {
228 eval [string map [list %WO% $wo %TN% $tn] {
229 do_execsql_test 2.%TN%.1 {
230 CREATE TABLE x1(a INTEGER PRIMARY KEY, b) %WO%;
231 INSERT INTO x1 VALUES
232 (1, 'one'), (2, 'two'), (3, 'three'), (4, 'four'),
233 (5, 'five'), (6, 'six'), (7, 'seven'), (8, 'eight');
236 do_execsql_test 2.%TN%.2 {
237 CREATE TABLE data1(x, y);
238 INSERT INTO data1 VALUES
239 (1, 'eleven'), (1, 'twenty-one'), (2, 'twelve'), (2, 'twenty-two'),
240 (3, 'thirteen'), (3, 'twenty-three'), (4, 'fourteen'), (4, 'twenty-four');
243 do_execsql_test 2.%TN%.3 {
244 UPDATE x1 SET b=y FROM data1 WHERE a=x ORDER BY a LIMIT 3;
247 1 eleven 2 twelve 3 thirteen 4 four 5 five 6 six 7 seven 8 eight
250 do_execsql_test 2.%TN%.4 {
251 UPDATE x1 SET b=b||y FROM data1 WHERE a=x ORDER BY b LIMIT 3;
254 1 eleveneleven 2 twelve 3 thirteenthirteen 4 fourfourteen
255 5 five 6 six 7 seven 8 eight
258 do_catchsql_test 2.%TN%.5 {
259 UPDATE x1 SET b=b||b ORDER BY b;
260 } {1 {ORDER BY without LIMIT on UPDATE}}
261 do_catchsql_test 2.%TN%.6 {
262 UPDATE x1 SET b=b||y FROM data1 WHERE a=x ORDER BY b;
263 } {1 {ORDER BY without LIMIT on UPDATE}}
265 #-----------------------------------------------------------------------
267 do_execsql_test 2.%TN%.6 {
269 CREATE TABLE x1(u, v, b, PRIMARY KEY(u, v)) %WO%;
270 INSERT INTO x1 VALUES
271 (0, 1, 'one'), (1, 0, 'two'), (1, 1, 'three'), (2, 0, 'four'),
272 (2, 1, 'five'), (3, 0, 'six'), (3, 1, 'seven'), (4, 0, 'eight');
275 do_execsql_test 2.%TN%.7 {
276 UPDATE x1 SET b=y FROM data1 WHERE (u*2+v)=x ORDER BY u, v LIMIT 3;
279 0 1 eleven 1 0 twelve 1 1 thirteen 2 0 four
280 2 1 five 3 0 six 3 1 seven 4 0 eight
283 do_execsql_test 2.%TN%.8 {
284 UPDATE x1 SET b=b||y FROM data1 WHERE (u*2+v)=x ORDER BY b LIMIT 3;
287 0 1 eleveneleven 1 0 twelve 1 1 thirteenthirteen 2 0 fourfourteen
288 2 1 five 3 0 six 3 1 seven 4 0 eight
296 do_execsql_test 3.0 {
297 CREATE TABLE data(x, y, z);
298 CREATE VIEW t1 AS SELECT * FROM data;
299 CREATE TRIGGER t1_insert INSTEAD OF INSERT ON t1 BEGIN
300 INSERT INTO data VALUES(new.x, new.y, new.z);
302 CREATE TRIGGER t1_update INSTEAD OF UPDATE ON t1 BEGIN
303 INSERT INTO log VALUES(old.z || '->' || new.z);
306 CREATE TABLE log(t TEXT);
308 INSERT INTO t1 VALUES(1, 'i', 'one');
309 INSERT INTO t1 VALUES(2, 'ii', 'two');
310 INSERT INTO t1 VALUES(3, 'iii', 'three');
311 INSERT INTO t1 VALUES(4, 'iv', 'four');
314 do_execsql_test 3.1 {
315 WITH input(k, v) AS (
316 VALUES(3, 'thirty'), (1, 'ten')
318 UPDATE t1 SET z=v FROM input WHERE x=k;
323 CREATE TABLE x1(a INT PRIMARY KEY, b, c) WITHOUT ROWID;
326 CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c);
329 CREATE TABLE x1(a INT PRIMARY KEY, b, c);
336 do_execsql_test 4.$tn.0 {
337 INSERT INTO x1 VALUES(1, 1, 1);
338 INSERT INTO x1 VALUES(2, 2, 2);
339 INSERT INTO x1 VALUES(3, 3, 3);
340 INSERT INTO x1 VALUES(4, 4, 4);
341 INSERT INTO x1 VALUES(5, 5, 5);
342 CREATE TABLE map(o, t);
343 INSERT INTO map VALUES(3, 30), (4, 40), (1, 10);
346 do_execsql_test 4.$tn.1 {
347 UPDATE x1 SET a=t FROM map WHERE a=o;
348 SELECT * FROM x1 ORDER BY a;
349 } {2 2 2 5 5 5 10 1 1 30 3 3 40 4 4}
353 do_execsql_test 5.0 {
354 CREATE TABLE x1(a, b, c);
355 CREATE TABLE x2(a, b, c);
358 foreach {tn update nm} {
359 1 "UPDATE x1 SET a=5 FROM x1" x1
360 2 "UPDATE x1 AS grapes SET a=5 FROM x1 AS grapes" grapes
361 3 "UPDATE x1 SET a=5 FROM x2, x1" x1
362 4 "UPDATE x1 AS grapes SET a=5 FROM x2, x1 AS grapes" grapes
364 do_catchsql_test 5.$tn $update \
365 "1 {target object/alias may not appear in FROM clause: $nm}"