xref: /sqlite-3.40.0/test/upfrom2.test (revision 75c493f7)
19ed322d6Sdan# 2020 April 29
29ed322d6Sdan#
39ed322d6Sdan# The author disclaims copyright to this source code.  In place of
49ed322d6Sdan# a legal notice, here is a blessing:
59ed322d6Sdan#
69ed322d6Sdan#    May you do good and not evil.
79ed322d6Sdan#    May you find forgiveness for yourself and forgive others.
89ed322d6Sdan#    May you share freely, never taking more than you give.
99ed322d6Sdan#
109ed322d6Sdan#***********************************************************************
119ed322d6Sdan#
129ed322d6Sdan
139ed322d6Sdanset testdir [file dirname $argv0]
149ed322d6Sdansource $testdir/tester.tcl
159ed322d6Sdanset testprefix upfrom2
169ed322d6Sdan
179ed322d6Sdan# Test cases:
189ed322d6Sdan#
199ed322d6Sdan#   1.*: Test that triggers are fired correctly for UPDATE FROM statements,
20f2972b60Sdan#        and only once for each row. Except for INSTEAD OF triggers on
21f2972b60Sdan#        views - these are fired once for each row returned by the join,
22f2972b60Sdan#        including duplicates.
23f2972b60Sdan#
24f2972b60Sdan#   2.*: Test adding ORDER BY and LIMIT clauses with UPDATE FROM statements.
259ed322d6Sdan#
2607ca7d61Sdan#   5.*: Test that specifying the target table name or alias in the FROM
2707ca7d61Sdan#        clause of an UPDATE statement is an error.
2807ca7d61Sdan#
299ed322d6Sdan
309ed322d6Sdanforeach {tn wo} {
319ed322d6Sdan  1 ""
329ed322d6Sdan  2 "WITHOUT ROWID"
339ed322d6Sdan} {
349ed322d6Sdan  reset_db
359ed322d6Sdan
369ed322d6Sdan  eval [string map [list %WO% $wo %TN% $tn] {
379ed322d6Sdan  do_execsql_test 1.%TN%.0 {
389ed322d6Sdan    CREATE TABLE log(t TEXT);
399ed322d6Sdan    CREATE TABLE t1(x PRIMARY KEY, y, z UNIQUE) %WO%;
409ed322d6Sdan    CREATE INDEX t1y ON t1(y);
419ed322d6Sdan
429ed322d6Sdan    INSERT INTO t1 VALUES(1, 'i',   'one');
439ed322d6Sdan    INSERT INTO t1 VALUES(2, 'ii',  'two');
449ed322d6Sdan    INSERT INTO t1 VALUES(3, 'iii', 'three');
459ed322d6Sdan    INSERT INTO t1 VALUES(4, 'iv',  'four');
469ed322d6Sdan
479ed322d6Sdan    CREATE TRIGGER tr1 BEFORE UPDATE ON t1 BEGIN
489ed322d6Sdan      INSERT INTO log VALUES(old.z || '->' || new.z);
499ed322d6Sdan    END;
509ed322d6Sdan    CREATE TRIGGER tr2 AFTER UPDATE ON t1 BEGIN
519ed322d6Sdan      INSERT INTO log VALUES(old.y || '->' || new.y);
529ed322d6Sdan    END;
539ed322d6Sdan  }
549ed322d6Sdan
559ed322d6Sdan  do_execsql_test 1.%TN%.1 {
569ed322d6Sdan    WITH data(k, v) AS (
579ed322d6Sdan      VALUES(3, 'thirty'), (1, 'ten')
589ed322d6Sdan    )
599ed322d6Sdan    UPDATE t1 SET z=v FROM data WHERE x=k;
609ed322d6Sdan
619ed322d6Sdan    SELECT * FROM t1;
629ed322d6Sdan    SELECT * FROM log;
639ed322d6Sdan  } {
649ed322d6Sdan    1 i ten   2 ii two   3 iii thirty   4 iv four
659ed322d6Sdan    one->ten        i->i
669ed322d6Sdan    three->thirty   iii->iii
679ed322d6Sdan  }
689ed322d6Sdan
699ed322d6Sdan  do_execsql_test 1.%TN%.2 {
709ed322d6Sdan    CREATE TABLE t2(a, b);
719ed322d6Sdan    CREATE TABLE t3(k, v);
729ed322d6Sdan
739ed322d6Sdan    INSERT INTO t3 VALUES(5,   'v');
749ed322d6Sdan    INSERT INTO t3 VALUES(12, 'xii');
759ed322d6Sdan
769ed322d6Sdan    INSERT INTO t2 VALUES(2, 12);
779ed322d6Sdan    INSERT INTO t2 VALUES(3, 5);
789ed322d6Sdan
799ed322d6Sdan    DELETE FROM log;
809ed322d6Sdan    UPDATE t1 SET y=v FROM t2, t3 WHERE t1.x=t2.a AND t3.k=t2.b;
819ed322d6Sdan
829ed322d6Sdan    SELECT * FROM t1;
839ed322d6Sdan    SELECT * FROM log;
849ed322d6Sdan  } {
859ed322d6Sdan    1 i ten   2 xii two   3 v thirty   4 iv four
869ed322d6Sdan    two->two         ii->xii
879ed322d6Sdan    thirty->thirty   iii->v
889ed322d6Sdan  }
899ed322d6Sdan
909ed322d6Sdan  do_execsql_test 1.%TN%.3 {
919ed322d6Sdan    DELETE FROM log;
929ed322d6Sdan    WITH data(k, v) AS (
939ed322d6Sdan      VALUES(1, 'seven'), (1, 'eight'), (2, 'eleven'), (2, 'twelve')
949ed322d6Sdan    )
959ed322d6Sdan    UPDATE t1 SET z=v FROM data WHERE x=k;
969ed322d6Sdan
979ed322d6Sdan    SELECT * FROM t1;
989ed322d6Sdan    SELECT * FROM log;
999ed322d6Sdan  } {
1009ed322d6Sdan    1 i eight   2 xii twelve   3 v thirty   4 iv four
1019ed322d6Sdan    ten->eight        i->i
1029ed322d6Sdan    two->twelve       xii->xii
1039ed322d6Sdan  }
104f2972b60Sdan
105f2972b60Sdan  do_test 1.%TN%.4 { db changes } {2}
106f2972b60Sdan
107f2972b60Sdan  do_execsql_test 1.%TN%.5 {
108f2972b60Sdan    CREATE VIEW v1 AS SELECT * FROM t1;
109f2972b60Sdan    CREATE TRIGGER v1tr INSTEAD OF UPDATE ON v1 BEGIN
110f2972b60Sdan      UPDATE t1 SET y=new.y, z=new.z WHERE x=new.x;
111f2972b60Sdan    END;
112f2972b60Sdan
113f2972b60Sdan    DELETE FROM log;
114f2972b60Sdan    WITH data(k, v) AS (
115f2972b60Sdan      VALUES(3, 'thirteen'), (3, 'fourteen'), (4, 'fifteen'), (4, 'sixteen')
116f2972b60Sdan    )
117f2972b60Sdan    UPDATE v1 SET z=v FROM data WHERE x=k;
118f2972b60Sdan  }
119f2972b60Sdan
120f2972b60Sdan  do_execsql_test 1.%TN%.6 {
121f2972b60Sdan    SELECT * FROM v1;
122f2972b60Sdan    SELECT * FROM log;
123f2972b60Sdan  } {
124f2972b60Sdan    1 i eight   2 xii twelve   3 v fourteen   4 iv sixteen
125f2972b60Sdan    thirty->thirteen  v->v
126f2972b60Sdan    thirteen->fourteen  v->v
127f2972b60Sdan    four->fifteen  iv->iv
128f2972b60Sdan    fifteen->sixteen  iv->iv
129f2972b60Sdan  }
130f2972b60Sdan
1311e113844Sdan  #--------------------------------------------------------------
1321e113844Sdan
1331e113844Sdan  do_execsql_test 1.%TN%.7 {
1341e113844Sdan    CREATE TABLE o1(w, x, y, z UNIQUE, PRIMARY KEY(w, x)) %WO%;
1351e113844Sdan    CREATE INDEX o1y ON t1(y);
1361e113844Sdan
1371e113844Sdan    INSERT INTO o1 VALUES(0, 0, 'i', 'one');
1381e113844Sdan    INSERT INTO o1 VALUES(0, 1, 'ii', 'two');
1391e113844Sdan    INSERT INTO o1 VALUES(1, 0, 'iii', 'three');
1401e113844Sdan    INSERT INTO o1 VALUES(1, 1, 'iv', 'four');
1411e113844Sdan
1421e113844Sdan    CREATE TRIGGER tro1 BEFORE UPDATE ON o1 BEGIN
1431e113844Sdan      INSERT INTO log VALUES(old.z || '->' || new.z);
1441e113844Sdan    END;
1451e113844Sdan    CREATE TRIGGER tro2 AFTER UPDATE ON o1 BEGIN
1461e113844Sdan      INSERT INTO log VALUES(old.y || '->' || new.y);
1471e113844Sdan    END;
1481e113844Sdan  }
1491e113844Sdan
1501e113844Sdan  do_execsql_test 1.%TN%.8 {
1511e113844Sdan    DELETE FROM log;
1521e113844Sdan    WITH data(k, v) AS (
1531e113844Sdan      VALUES(3, 'thirty'), (1, 'ten')
1541e113844Sdan    )
1551e113844Sdan    UPDATE o1 SET z=v FROM data WHERE (1+x+w*2)=k;
1561e113844Sdan
1571e113844Sdan    SELECT * FROM o1;
1581e113844Sdan    SELECT * FROM log;
1591e113844Sdan  } {
1601e113844Sdan    0 0 i ten   0 1 ii two   1 0 iii thirty   1 1 iv four
1611e113844Sdan    one->ten        i->i
1621e113844Sdan    three->thirty   iii->iii
1631e113844Sdan  }
1641e113844Sdan
1651e113844Sdan  do_execsql_test 1.%TN%.9 {
1661e113844Sdan    DELETE FROM log;
1671e113844Sdan    UPDATE o1 SET y=v FROM t2, t3 WHERE (1+o1.w*2+o1.x)=t2.a AND t3.k=t2.b;
1681e113844Sdan
1691e113844Sdan    SELECT * FROM o1;
1701e113844Sdan    SELECT * FROM log;
1711e113844Sdan  } {
1721e113844Sdan    0 0 i ten   0 1 xii two   1 0 v thirty   1 1 iv four
1731e113844Sdan    two->two         ii->xii
1741e113844Sdan    thirty->thirty   iii->v
1751e113844Sdan  }
1761e113844Sdan
1771e113844Sdan  do_execsql_test 1.%TN%.10 {
1781e113844Sdan    DELETE FROM log;
1791e113844Sdan    WITH data(k, v) AS (
1801e113844Sdan      VALUES(1, 'seven'), (1, 'eight'), (2, 'eleven'), (2, 'twelve')
1811e113844Sdan    )
1821e113844Sdan    UPDATE o1 SET z=v FROM data WHERE (1+w*2+x)=k;
1831e113844Sdan
1841e113844Sdan    SELECT * FROM o1;
1851e113844Sdan    SELECT * FROM log;
1861e113844Sdan  } {
1871e113844Sdan    0 0 i eight   0 1 xii twelve   1 0 v thirty   1 1 iv four
1881e113844Sdan    ten->eight        i->i
1891e113844Sdan    two->twelve       xii->xii
1901e113844Sdan  }
1911e113844Sdan
1921e113844Sdan  do_test 1.%TN%.11 { db changes } {2}
1931e113844Sdan
1941e113844Sdan  do_execsql_test 1.%TN%.12 {
1951e113844Sdan    CREATE VIEW w1 AS SELECT * FROM o1;
1961e113844Sdan    CREATE TRIGGER w1tr INSTEAD OF UPDATE ON w1 BEGIN
1971e113844Sdan      UPDATE o1 SET y=new.y, z=new.z WHERE w=new.w AND x=new.x;
1981e113844Sdan    END;
1991e113844Sdan
2001e113844Sdan    DELETE FROM log;
2011e113844Sdan    WITH data(k, v) AS (
2021e113844Sdan      VALUES(3, 'thirteen'), (3, 'fourteen'), (4, 'fifteen'), (4, 'sixteen')
2031e113844Sdan    )
2041e113844Sdan    UPDATE w1 SET z=v FROM data WHERE (1+w*2+x)=k;
2051e113844Sdan  }
2061e113844Sdan
2071e113844Sdan  do_execsql_test 1.%TN%.13 {
2081e113844Sdan    SELECT * FROM w1;
2091e113844Sdan    SELECT * FROM log;
2101e113844Sdan  } {
2111e113844Sdan    0 0 i eight   0 1 xii twelve   1 0 v fourteen   1 1 iv sixteen
2121e113844Sdan    thirty->thirteen  v->v
2131e113844Sdan    thirteen->fourteen  v->v
2141e113844Sdan    four->fifteen  iv->iv
2151e113844Sdan    fifteen->sixteen  iv->iv
2161e113844Sdan  }
2171e113844Sdan
2189ed322d6Sdan}]
2199ed322d6Sdan}
2209ed322d6Sdan
221f2972b60Sdanifcapable update_delete_limit {
222f2972b60Sdanforeach {tn wo} {
223f2972b60Sdan  1 ""
224f2972b60Sdan  2 "WITHOUT ROWID"
225f2972b60Sdan} {
226f2972b60Sdan  reset_db
227f2972b60Sdan
228f2972b60Sdaneval [string map [list %WO% $wo %TN% $tn] {
229f2972b60Sdan  do_execsql_test 2.%TN%.1 {
230f2972b60Sdan    CREATE TABLE x1(a INTEGER PRIMARY KEY, b) %WO%;
231f2972b60Sdan    INSERT INTO x1 VALUES
232f2972b60Sdan        (1, 'one'), (2, 'two'), (3, 'three'), (4, 'four'),
233f2972b60Sdan        (5, 'five'), (6, 'six'), (7, 'seven'), (8, 'eight');
234f2972b60Sdan  }
235f2972b60Sdan
236f2972b60Sdan  do_execsql_test 2.%TN%.2 {
237f2972b60Sdan    CREATE TABLE data1(x, y);
238f2972b60Sdan    INSERT INTO data1 VALUES
239f2972b60Sdan    (1, 'eleven'), (1, 'twenty-one'), (2, 'twelve'), (2, 'twenty-two'),
240f2972b60Sdan    (3, 'thirteen'), (3, 'twenty-three'), (4, 'fourteen'), (4, 'twenty-four');
241f2972b60Sdan  }
242f2972b60Sdan
243f2972b60Sdan  do_execsql_test 2.%TN%.3 {
244f2972b60Sdan    UPDATE x1 SET b=y FROM data1 WHERE a=x ORDER BY a LIMIT 3;
245f2972b60Sdan    SELECT * FROM x1;
246f2972b60Sdan  } {
247f2972b60Sdan    1 eleven 2 twelve 3 thirteen 4 four 5 five 6 six 7 seven 8 eight
248f2972b60Sdan  }
249f2972b60Sdan
250f2972b60Sdan  do_execsql_test 2.%TN%.4 {
251f2972b60Sdan    UPDATE x1 SET b=b||y FROM data1 WHERE a=x ORDER BY b LIMIT 3;
252f2972b60Sdan    SELECT * FROM x1;
253f2972b60Sdan  } {
254f2972b60Sdan    1 eleveneleven 2 twelve 3 thirteenthirteen 4 fourfourteen
255f2972b60Sdan    5 five 6 six 7 seven 8 eight
256f2972b60Sdan  }
257f2972b60Sdan
2581e113844Sdan  do_catchsql_test 2.%TN%.5 {
2591e113844Sdan    UPDATE x1 SET b=b||b ORDER BY b;
2601e113844Sdan  } {1 {ORDER BY without LIMIT on UPDATE}}
2611e113844Sdan  do_catchsql_test 2.%TN%.6 {
2621e113844Sdan    UPDATE x1 SET b=b||y FROM data1 WHERE a=x ORDER BY b;
2631e113844Sdan  } {1 {ORDER BY without LIMIT on UPDATE}}
2641e113844Sdan
2651e113844Sdan  #-----------------------------------------------------------------------
2661e113844Sdan
2671e113844Sdan  do_execsql_test 2.%TN%.6 {
2681e113844Sdan    DROP TABLE x1;
2691e113844Sdan    CREATE TABLE x1(u, v, b, PRIMARY KEY(u, v)) %WO%;
2701e113844Sdan    INSERT INTO x1 VALUES
2711e113844Sdan        (0, 1, 'one'), (1, 0, 'two'), (1, 1, 'three'), (2, 0, 'four'),
2721e113844Sdan        (2, 1, 'five'), (3, 0, 'six'), (3, 1, 'seven'), (4, 0, 'eight');
2731e113844Sdan  }
2741e113844Sdan
2751e113844Sdan  do_execsql_test 2.%TN%.7 {
2761e113844Sdan    UPDATE x1 SET b=y FROM data1 WHERE (u*2+v)=x ORDER BY u, v LIMIT 3;
2771e113844Sdan    SELECT * FROM x1;
2781e113844Sdan  } {
2791e113844Sdan    0 1 eleven 1 0 twelve 1 1 thirteen 2 0 four
2801e113844Sdan    2 1 five 3 0 six 3 1 seven 4 0 eight
2811e113844Sdan  }
2821e113844Sdan
2831e113844Sdan  do_execsql_test 2.%TN%.8 {
2841e113844Sdan    UPDATE x1 SET b=b||y FROM data1 WHERE (u*2+v)=x ORDER BY b LIMIT 3;
2851e113844Sdan    SELECT * FROM x1;
2861e113844Sdan  } {
2871e113844Sdan    0 1 eleveneleven 1 0 twelve 1 1 thirteenthirteen 2 0 fourfourteen
2881e113844Sdan    2 1 five  3 0 six 3 1 seven 4 0 eight
2891e113844Sdan  }
2901e113844Sdan
2911e113844Sdan
292f2972b60Sdan}]
293f2972b60Sdan}}
2949ed322d6Sdan
2958b023cf5Sdanreset_db
2968b023cf5Sdando_execsql_test 3.0 {
2978b023cf5Sdan  CREATE TABLE data(x, y, z);
2988b023cf5Sdan  CREATE VIEW t1 AS SELECT * FROM data;
2998b023cf5Sdan  CREATE TRIGGER t1_insert INSTEAD OF INSERT ON t1 BEGIN
3008b023cf5Sdan    INSERT INTO data VALUES(new.x, new.y, new.z);
3018b023cf5Sdan  END;
3028b023cf5Sdan  CREATE TRIGGER t1_update INSTEAD OF UPDATE ON t1 BEGIN
3038b023cf5Sdan    INSERT INTO log VALUES(old.z || '->' || new.z);
3048b023cf5Sdan  END;
3058b023cf5Sdan
3068b023cf5Sdan  CREATE TABLE log(t TEXT);
3078b023cf5Sdan
3088b023cf5Sdan  INSERT INTO t1 VALUES(1, 'i',   'one');
3098b023cf5Sdan  INSERT INTO t1 VALUES(2, 'ii',  'two');
3108b023cf5Sdan  INSERT INTO t1 VALUES(3, 'iii', 'three');
3118b023cf5Sdan  INSERT INTO t1 VALUES(4, 'iv',  'four');
3128b023cf5Sdan}
3138b023cf5Sdan
3148b023cf5Sdando_execsql_test 3.1 {
3158b023cf5Sdan  WITH input(k, v) AS (
3168b023cf5Sdan      VALUES(3, 'thirty'), (1, 'ten')
3178b023cf5Sdan  )
3188b023cf5Sdan  UPDATE t1 SET z=v FROM input WHERE x=k;
3198b023cf5Sdan}
3209ed322d6Sdan
3217465787bSdanforeach {tn sql} {
3227465787bSdan  2 {
3237465787bSdan    CREATE TABLE x1(a INT PRIMARY KEY, b, c) WITHOUT ROWID;
3247465787bSdan  }
3257465787bSdan  1 {
3267465787bSdan    CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c);
3277465787bSdan  }
3287465787bSdan  3 {
3297465787bSdan    CREATE TABLE x1(a INT PRIMARY KEY, b, c);
3307465787bSdan  }
3317465787bSdan} {
3327465787bSdan
3337465787bSdan  reset_db
3347465787bSdan  execsql $sql
3357465787bSdan
3367465787bSdan  do_execsql_test 4.$tn.0 {
3377465787bSdan    INSERT INTO x1 VALUES(1, 1, 1);
3387465787bSdan    INSERT INTO x1 VALUES(2, 2, 2);
3397465787bSdan    INSERT INTO x1 VALUES(3, 3, 3);
3407465787bSdan    INSERT INTO x1 VALUES(4, 4, 4);
3417465787bSdan    INSERT INTO x1 VALUES(5, 5, 5);
3427465787bSdan    CREATE TABLE map(o, t);
3437465787bSdan    INSERT INTO map VALUES(3, 30), (4, 40), (1, 10);
3447465787bSdan  }
3457465787bSdan
3467465787bSdan  do_execsql_test 4.$tn.1 {
3477465787bSdan    UPDATE x1 SET a=t FROM map WHERE a=o;
3487465787bSdan    SELECT * FROM x1 ORDER BY a;
3497465787bSdan  } {2 2 2   5 5 5   10 1 1  30 3 3  40 4 4}
3507465787bSdan}
3517465787bSdan
35207ca7d61Sdanreset_db
35307ca7d61Sdando_execsql_test 5.0 {
35407ca7d61Sdan  CREATE TABLE x1(a, b, c);
35507ca7d61Sdan  CREATE TABLE x2(a, b, c);
35607ca7d61Sdan}
35707ca7d61Sdan
35807ca7d61Sdanforeach {tn update nm} {
35907ca7d61Sdan  1 "UPDATE x1 SET a=5 FROM x1" x1
36007ca7d61Sdan  2 "UPDATE x1 AS grapes SET a=5 FROM x1 AS grapes" grapes
36107ca7d61Sdan  3 "UPDATE x1 SET a=5 FROM x2, x1" x1
36207ca7d61Sdan  4 "UPDATE x1 AS grapes SET a=5 FROM x2, x1 AS grapes" grapes
36307ca7d61Sdan} {
36407ca7d61Sdan  do_catchsql_test 5.$tn $update \
36507ca7d61Sdan    "1 {target object/alias may not appear in FROM clause: $nm}"
36607ca7d61Sdan}
36707ca7d61Sdan
3685daf69e5Sdan#--------------------------------------------------------------------------
3695daf69e5Sdanreset_db
3705daf69e5Sdando_execsql_test 6.0 {
3715daf69e5Sdan  CREATE TABLE t1(a);
3725daf69e5Sdan}
3735daf69e5Sdan
3745daf69e5Sdando_execsql_test 6.1 {
3755daf69e5Sdan  UPDATE t1 SET a = 1 FROM (
3765daf69e5Sdan      SELECT * FROM t1
3775daf69e5Sdan  )
3785daf69e5Sdan} {}
3795daf69e5Sdando_execsql_test 6.2 {
3805daf69e5Sdan  UPDATE t1 SET a = 1 FROM (
3815daf69e5Sdan      SELECT * FROM t1 UNION ALL SELECT * FROM t1
3825daf69e5Sdan  )
3835daf69e5Sdan} {}
38407ca7d61Sdan
385*75c493f7Sdrh# 2022-03-21
386*75c493f7Sdrh# https://sqlite.org/forum/forumpost/929168fdd6
387*75c493f7Sdrh#
388*75c493f7Sdrhreset_db
389*75c493f7Sdrhdo_execsql_test 7.0 {
390*75c493f7Sdrh  CREATE TABLE t1(a);
391*75c493f7Sdrh  INSERT INTO t1(a) VALUES(11),(22),(33),(44),(55);
392*75c493f7Sdrh  CREATE VIEW t2(b,c) AS SELECT a, COUNT(*) OVER () FROM t1;
393*75c493f7Sdrh  CREATE TABLE t3(x,y);
394*75c493f7Sdrh  CREATE TRIGGER t2r1 INSTEAD OF UPDATE ON t2 BEGIN
395*75c493f7Sdrh    INSERT INTO t3(x,y) VALUES(new.b,new.c);
396*75c493f7Sdrh  END;
397*75c493f7Sdrh  SELECT * FROM t2;
398*75c493f7Sdrh} {11 5 22 5 33 5 44 5 55 5}
399*75c493f7Sdrhdo_execsql_test 7.1 {
400*75c493f7Sdrh  UPDATE t2 SET c=t1.a FROM t1 WHERE t2.b=t1.a;
401*75c493f7Sdrh  SELECT * FROM t3;
402*75c493f7Sdrh} {11 11 22 22 33 33 44 44 55 55}
403*75c493f7Sdrh
404*75c493f7Sdrh
4059ed322d6Sdanfinish_test
406