xref: /sqlite-3.40.0/test/update2.test (revision 247c1b4a)
1f91c1318Sdan# 2017 January 9
2f91c1318Sdan#
3f91c1318Sdan# The author disclaims copyright to this source code.  In place of
4f91c1318Sdan# a legal notice, here is a blessing:
5f91c1318Sdan#
6f91c1318Sdan#    May you do good and not evil.
7f91c1318Sdan#    May you find forgiveness for yourself and forgive others.
8f91c1318Sdan#    May you share freely, never taking more than you give.
9f91c1318Sdan#
10f91c1318Sdan#***********************************************************************
11f91c1318Sdan#
12f91c1318Sdan
13f91c1318Sdanset testdir [file dirname $argv0]
14f91c1318Sdansource $testdir/tester.tcl
15f91c1318Sdanset testprefix update2
16f91c1318Sdan
17f91c1318Sdandb func repeat [list string repeat]
18f91c1318Sdan
19f91c1318Sdan#-------------------------------------------------------------------------
20f91c1318Sdan# 1.1.* A one-pass UPDATE that does balance() operations on the IPK index
21f91c1318Sdan#       that it is scanning.
22f91c1318Sdan#
23f91c1318Sdan# 1.2.* Same again, but with a WITHOUT ROWID table.
24f91c1318Sdan#
25f91c1318Sdanset nrow [expr 10]
26f91c1318Sdando_execsql_test 1.1.0 {
27f91c1318Sdan  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
28f91c1318Sdan  CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
29f91c1318Sdan  WITH s(i) AS ( SELECT 0 UNION ALL SELECT i+1 FROM s WHERE i<$nrow )
30f91c1318Sdan  INSERT INTO t1(b) SELECT char((i % 26) + 65) FROM s;
31f91c1318Sdan  INSERT INTO t2 SELECT * FROM t1;
32f91c1318Sdan}
33f91c1318Sdan
34f91c1318Sdando_execsql_test 1.1.1 {
35f91c1318Sdan  UPDATE t1 SET b = repeat(b, 100)
36f91c1318Sdan}
37f91c1318Sdan
38f91c1318Sdando_execsql_test 1.1.2 {
39f91c1318Sdan  SELECT * FROM t1;
40f91c1318Sdan} [db eval { SELECT a, repeat(b, 100) FROM t2 }]
41f91c1318Sdan
42f91c1318Sdando_execsql_test 1.2.0 {
43f91c1318Sdan  DROP TABLE t1;
44f91c1318Sdan  CREATE TABLE t1(a INT PRIMARY KEY, b) WITHOUT ROWID;
45f91c1318Sdan  WITH s(i) AS ( SELECT 0 UNION ALL SELECT i+1 FROM s WHERE i<$nrow )
46f91c1318Sdan  INSERT INTO t1(a, b) SELECT i+1, char((i % 26) + 65) FROM s;
47f91c1318Sdan}
48f91c1318Sdan
49f91c1318Sdan#explain_i { UPDATE t1 SET b = repeat(b, 100) }
50f91c1318Sdando_execsql_test 1.2.1 {
51f91c1318Sdan  UPDATE t1 SET b = repeat(b, 100)
52f91c1318Sdan}
53f91c1318Sdan
54f91c1318Sdando_execsql_test 1.2.2 {
55f91c1318Sdan  SELECT * FROM t1;
56f91c1318Sdan} [db eval { SELECT a, repeat(b, 100) FROM t2 }]
57f91c1318Sdan
58f91c1318Sdan
59f91c1318Sdan#-------------------------------------------------------------------------
60f91c1318Sdan# A one-pass UPDATE that does balance() operations on the IPK index
61f91c1318Sdan# that it is scanning.
62f91c1318Sdan#
63f91c1318Sdando_execsql_test 2.1 {
64f91c1318Sdan  CREATE TABLE t3(a PRIMARY KEY, b, c);
65f91c1318Sdan  CREATE INDEX t3i ON t3(b);
66f91c1318Sdan} {}
67f91c1318Sdando_execsql_test 2.2 { UPDATE t3 SET c=1 WHERE b=?      } {}
68f91c1318Sdando_execsql_test 2.3 { UPDATE t3 SET c=1 WHERE rowid=?  } {}
69f91c1318Sdan
70f91c1318Sdan#-------------------------------------------------------------------------
71f91c1318Sdan#
72f91c1318Sdando_execsql_test 3.0 {
73f91c1318Sdan  CREATE TABLE t4(a PRIMARY KEY, b, c) WITHOUT ROWID;
74f91c1318Sdan  CREATE INDEX t4c ON t4(c);
75f91c1318Sdan  INSERT INTO t4 VALUES(1, 2, 3);
76f91c1318Sdan  INSERT INTO t4 VALUES(2, 3, 4);
77f91c1318Sdan}
78f91c1318Sdan
79f91c1318Sdando_execsql_test 3.1 {
80f91c1318Sdan  UPDATE t4 SET c=c+2 WHERE c>2;
81f91c1318Sdan  SELECT a, c FROM t4 ORDER BY a;
82f91c1318Sdan} {1 5 2 6}
83f91c1318Sdan
84372f942fSdan#-------------------------------------------------------------------------
85372f942fSdan#
86372f942fSdanforeach {tn sql} {
872c6fec21Sdan  1 {
882c6fec21Sdan    CREATE TABLE b1(a INTEGER PRIMARY KEY, b, c);
892c6fec21Sdan    CREATE TABLE c1(a INTEGER PRIMARY KEY, b, c, d)
902c6fec21Sdan  }
912c6fec21Sdan  2 {
922c6fec21Sdan    CREATE TABLE b1(a INT PRIMARY KEY, b, c) WITHOUT ROWID;
932c6fec21Sdan    CREATE TABLE c1(a INT PRIMARY KEY, b, c, d) WITHOUT ROWID;
942c6fec21Sdan  }
95372f942fSdan} {
962c6fec21Sdan  execsql { DROP TABLE IF EXISTS b1; DROP TABLE IF EXISTS c1; }
97372f942fSdan  execsql $sql
982c6fec21Sdan
99372f942fSdan  do_execsql_test 4.$tn.0 {
100372f942fSdan    CREATE UNIQUE INDEX b1c ON b1(c);
101372f942fSdan    INSERT INTO b1 VALUES(1, 'a', 1);
102372f942fSdan    INSERT INTO b1 VALUES(2, 'b', 15);
103372f942fSdan    INSERT INTO b1 VALUES(3, 'c', 3);
104372f942fSdan    INSERT INTO b1 VALUES(4, 'd', 4);
105372f942fSdan    INSERT INTO b1 VALUES(5, 'e', 5);
106372f942fSdan    INSERT INTO b1 VALUES(6, 'f', 6);
107372f942fSdan    INSERT INTO b1 VALUES(7, 'g', 7);
108372f942fSdan  }
109372f942fSdan
110372f942fSdan  do_execsql_test 4.$tn.1 {
111372f942fSdan    UPDATE OR REPLACE b1 SET c=c+10 WHERE a BETWEEN 4 AND 7;
112372f942fSdan    SELECT * FROM b1 ORDER BY a;
113372f942fSdan  } {
114372f942fSdan    1 a 1
115372f942fSdan    3 c 3
116372f942fSdan    4 d 14
117372f942fSdan    5 e 15
118372f942fSdan    6 f 16
119372f942fSdan    7 g 17
120372f942fSdan  }
1212c6fec21Sdan
1222c6fec21Sdan  do_execsql_test 4.$tn.2 {
1232c6fec21Sdan    CREATE INDEX c1d ON c1(d, b);
1242c6fec21Sdan    CREATE UNIQUE INDEX c1c ON c1(c, b);
1252c6fec21Sdan
1262c6fec21Sdan    INSERT INTO c1 VALUES(1, 'a', 1,  1);
1272c6fec21Sdan    INSERT INTO c1 VALUES(2, 'a', 15, 2);
1282c6fec21Sdan    INSERT INTO c1 VALUES(3, 'a', 3,  3);
1292c6fec21Sdan    INSERT INTO c1 VALUES(4, 'a', 4,  4);
1302c6fec21Sdan    INSERT INTO c1 VALUES(5, 'a', 5,  5);
1312c6fec21Sdan    INSERT INTO c1 VALUES(6, 'a', 6,  6);
1322c6fec21Sdan    INSERT INTO c1 VALUES(7, 'a', 7,  7);
133372f942fSdan  }
134372f942fSdan
1352c6fec21Sdan  do_execsql_test 4.$tn.3 {
1362c6fec21Sdan    UPDATE OR REPLACE c1 SET c=c+10 WHERE d BETWEEN 4 AND 7;
1372c6fec21Sdan    SELECT * FROM c1 ORDER BY a;
1382c6fec21Sdan  } {
1392c6fec21Sdan    1 a 1 1
1402c6fec21Sdan    3 a 3 3
1412c6fec21Sdan    4 a 14 4
1422c6fec21Sdan    5 a 15 5
1432c6fec21Sdan    6 a 16 6
1442c6fec21Sdan    7 a 17 7
1452c6fec21Sdan  }
1462c6fec21Sdan
1472c6fec21Sdan  do_execsql_test 4.$tn.4 { PRAGMA integrity_check } ok
1482c6fec21Sdan
1492c6fec21Sdan  do_execsql_test 4.$tn.5 {
1502c6fec21Sdan    DROP INDEX c1d;
1512c6fec21Sdan    DROP INDEX c1c;
1522c6fec21Sdan    DELETE FROM c1;
1532c6fec21Sdan
1542c6fec21Sdan    INSERT INTO c1 VALUES(1, 'a', 1,  1);
1552c6fec21Sdan    INSERT INTO c1 VALUES(2, 'a', 15, 2);
1562c6fec21Sdan    INSERT INTO c1 VALUES(3, 'a', 3,  3);
1572c6fec21Sdan    INSERT INTO c1 VALUES(4, 'a', 4,  4);
1582c6fec21Sdan    INSERT INTO c1 VALUES(5, 'a', 5,  5);
1592c6fec21Sdan    INSERT INTO c1 VALUES(6, 'a', 6,  6);
1602c6fec21Sdan    INSERT INTO c1 VALUES(7, 'a', 7,  7);
1612c6fec21Sdan
1622c6fec21Sdan    CREATE INDEX c1d ON c1(d);
1632c6fec21Sdan    CREATE UNIQUE INDEX c1c ON c1(c);
1642c6fec21Sdan  }
1652c6fec21Sdan
1662c6fec21Sdan  do_execsql_test 4.$tn.6 {
1672c6fec21Sdan    UPDATE OR REPLACE c1 SET c=c+10 WHERE d BETWEEN 4 AND 7;
1682c6fec21Sdan    SELECT * FROM c1 ORDER BY a;
1692c6fec21Sdan  } {
1702c6fec21Sdan    1 a 1 1
1712c6fec21Sdan    3 a 3 3
1722c6fec21Sdan    4 a 14 4
1732c6fec21Sdan    5 a 15 5
1742c6fec21Sdan    6 a 16 6
1752c6fec21Sdan    7 a 17 7
1762c6fec21Sdan  }
1772c6fec21Sdan}
178372f942fSdan
179f64ece14Sdan#-------------------------------------------------------------------------
180f64ece14Sdan#
181f64ece14Sdando_execsql_test 5.0 {
182f64ece14Sdan  CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c);
183f64ece14Sdan  CREATE INDEX x1c ON x1(b, c);
184f64ece14Sdan  INSERT INTO x1 VALUES(1, 'a', 1);
185f64ece14Sdan  INSERT INTO x1 VALUES(2, 'a', 2);
186f64ece14Sdan  INSERT INTO x1 VALUES(3, 'a', 3);
187f64ece14Sdan}
188f64ece14Sdan
189f64ece14Sdando_execsql_test 5.1.1 {
190f64ece14Sdan  UPDATE x1 SET c=c+1 WHERE b='a';
191f64ece14Sdan}
192f64ece14Sdan
193f64ece14Sdando_execsql_test 5.1.2 {
194f64ece14Sdan  SELECT * FROM x1;
195f64ece14Sdan} {1 a 2 2 a 3 3 a 4}
196f64ece14Sdan
197f64ece14Sdando_test 5.2 {
198f64ece14Sdan  catch { array unset A }
199f64ece14Sdan  db eval { EXPLAIN UPDATE x1 SET c=c+1 WHERE b='a' } { incr A($opcode) }
200f64ece14Sdan  set A(NotExists)
201f64ece14Sdan} {1}
202f64ece14Sdan
2030c2ba13eSdan#-------------------------------------------------------------------------
2040c2ba13eSdando_execsql_test 6.0 {
2050c2ba13eSdan  CREATE TABLE d1(a,b);
2060c2ba13eSdan  CREATE INDEX d1b ON d1(a);
2070c2ba13eSdan  CREATE INDEX d1c ON d1(b);
2080c2ba13eSdan  INSERT INTO d1 VALUES(1,2);
2090c2ba13eSdan}
2100c2ba13eSdan
2110c2ba13eSdando_execsql_test 6.1 {
2120c2ba13eSdan  UPDATE d1 SET a = a+2 WHERE a>0 OR b>0;
2130c2ba13eSdan}
2140c2ba13eSdan
2150c2ba13eSdando_execsql_test 6.2 {
2160c2ba13eSdan  SELECT * FROM d1;
2170c2ba13eSdan} {3 2}
218f64ece14Sdan
219*247c1b4aSdrh# 2019-01-22 Bug in UPDATE OR REPLACE discovered by the
220*247c1b4aSdrh# Matt Denton's LPM fuzzer
221*247c1b4aSdrh#
222*247c1b4aSdrhdo_execsql_test 7.100 {
223*247c1b4aSdrh  DROP TABLE IF EXISTS t1;
224*247c1b4aSdrh  CREATE TABLE t1(x,y);
225*247c1b4aSdrh  CREATE UNIQUE INDEX t1x1 ON t1(x) WHERE x IS NOT NULL;
226*247c1b4aSdrh  INSERT INTO t1(x) VALUES(NULL),(NULL);
227*247c1b4aSdrh  CREATE INDEX t1x2 ON t1(y);
228*247c1b4aSdrh  SELECT quote(x), quote(y), '|' FROM t1;
229*247c1b4aSdrh} {NULL NULL | NULL NULL |}
230*247c1b4aSdrhdo_execsql_test 7.110 {
231*247c1b4aSdrh  UPDATE OR REPLACE t1 SET x=1;
232*247c1b4aSdrh  SELECT quote(x), quote(y), '|' FROM t1;
233*247c1b4aSdrh} {1 NULL |}
234*247c1b4aSdrh
235f91c1318Sdanfinish_test
236