xref: /sqlite-3.40.0/test/wherelimit2.test (revision 51da8daf)
1b3c16b89Sdan# 2008 October 6
2b3c16b89Sdan#
3b3c16b89Sdan# The author disclaims copyright to this source code.  In place of
4b3c16b89Sdan# a legal notice, here is a blessing:
5b3c16b89Sdan#
6b3c16b89Sdan#    May you do good and not evil.
7b3c16b89Sdan#    May you find forgiveness for yourself and forgive others.
8b3c16b89Sdan#    May you share freely, never taking more than you give.
9b3c16b89Sdan#
10b3c16b89Sdan#***********************************************************************
11b3c16b89Sdan# This file implements regression tests for SQLite library.  The
12b3c16b89Sdan# focus of this file is testing the LIMIT ... OFFSET ... clause
13b3c16b89Sdan#  of UPDATE and DELETE statements.
14b3c16b89Sdan#
15b3c16b89Sdan
16b3c16b89Sdanset testdir [file dirname $argv0]
17b3c16b89Sdansource $testdir/tester.tcl
18b3c16b89Sdanset testprefix wherelimit2
19b3c16b89Sdan
20b3c16b89Sdanifcapable !update_delete_limit {
21b3c16b89Sdan  finish_test
22b3c16b89Sdan  return
23b3c16b89Sdan}
24b3c16b89Sdan
2526caf5beSdan#-------------------------------------------------------------------------
2626caf5beSdan# Test with views and INSTEAD OF triggers.
2726caf5beSdan#
28b3c16b89Sdando_execsql_test 1.0 {
29b3c16b89Sdan  CREATE TABLE t1(a, b);
30b3c16b89Sdan  INSERT INTO t1 VALUES(1, 'f');
31b3c16b89Sdan  INSERT INTO t1 VALUES(2, 'e');
32b3c16b89Sdan  INSERT INTO t1 VALUES(3, 'd');
33b3c16b89Sdan  INSERT INTO t1 VALUES(4, 'c');
34b3c16b89Sdan  INSERT INTO t1 VALUES(5, 'b');
35b3c16b89Sdan  INSERT INTO t1 VALUES(6, 'a');
36b3c16b89Sdan
37b3c16b89Sdan  CREATE VIEW v1 AS SELECT a,b FROM t1;
38b3c16b89Sdan  CREATE TABLE log(op, a);
39b3c16b89Sdan
40b3c16b89Sdan  CREATE TRIGGER v1del INSTEAD OF DELETE ON v1 BEGIN
41b3c16b89Sdan    INSERT INTO log VALUES('delete', old.a);
42b3c16b89Sdan  END;
43b3c16b89Sdan
44b3c16b89Sdan  CREATE TRIGGER v1upd INSTEAD OF UPDATE ON v1 BEGIN
45b3c16b89Sdan    INSERT INTO log VALUES('update', old.a);
46b3c16b89Sdan  END;
47b3c16b89Sdan}
48b3c16b89Sdan
49b3c16b89Sdando_execsql_test 1.1 {
50b3c16b89Sdan  DELETE FROM v1 ORDER BY a LIMIT 3;
51b3c16b89Sdan  SELECT * FROM log; DELETE FROM log;
52b3c16b89Sdan} {
53b3c16b89Sdan  delete 1 delete 2 delete 3
54b3c16b89Sdan}
55b3c16b89Sdando_execsql_test 1.2 {
56b3c16b89Sdan  DELETE FROM v1 ORDER BY b LIMIT 3;
57b3c16b89Sdan  SELECT * FROM log; DELETE FROM log;
58b3c16b89Sdan} {
59b3c16b89Sdan  delete 6 delete 5 delete 4
60b3c16b89Sdan}
61b3c16b89Sdando_execsql_test 1.3 {
62b3c16b89Sdan  UPDATE v1 SET b = 555 ORDER BY a LIMIT 3;
63b3c16b89Sdan  SELECT * FROM log; DELETE FROM log;
64b3c16b89Sdan} {
65b3c16b89Sdan  update 1 update 2 update 3
66b3c16b89Sdan}
67b3c16b89Sdando_execsql_test 1.4 {
68b3c16b89Sdan  UPDATE v1 SET b = 555 ORDER BY b LIMIT 3;
69b3c16b89Sdan  SELECT * FROM log; DELETE FROM log;
70b3c16b89Sdan} {
71b3c16b89Sdan  update 6 update 5 update 4
72b3c16b89Sdan}
73b3c16b89Sdan
7426caf5beSdan#-------------------------------------------------------------------------
7526caf5beSdan# Simple test using WITHOUT ROWID table.
7626caf5beSdan#
77ca3e3c3fSdando_execsql_test 2.1.0 {
78b3c16b89Sdan  CREATE TABLE t2(a, b, c, PRIMARY KEY(a, b)) WITHOUT ROWID;
79b3c16b89Sdan  INSERT INTO t2 VALUES(1, 1, 'h');
80b3c16b89Sdan  INSERT INTO t2 VALUES(1, 2, 'g');
81b3c16b89Sdan  INSERT INTO t2 VALUES(2, 1, 'f');
82b3c16b89Sdan  INSERT INTO t2 VALUES(2, 2, 'e');
83b3c16b89Sdan  INSERT INTO t2 VALUES(3, 1, 'd');
84b3c16b89Sdan  INSERT INTO t2 VALUES(3, 2, 'c');
85b3c16b89Sdan  INSERT INTO t2 VALUES(4, 1, 'b');
86b3c16b89Sdan  INSERT INTO t2 VALUES(4, 2, 'a');
87b3c16b89Sdan}
88b3c16b89Sdan
89ca3e3c3fSdando_execsql_test 2.1.1 {
90b3c16b89Sdan  BEGIN;
91b3c16b89Sdan    DELETE FROM t2 WHERE b=1 ORDER BY c LIMIT 2;
92b3c16b89Sdan    SELECT c FROM t2 ORDER BY 1;
93b3c16b89Sdan  ROLLBACK;
94b3c16b89Sdan} {a c e f g h}
95b3c16b89Sdan
96ca3e3c3fSdando_execsql_test 2.1.2 {
97b3c16b89Sdan  BEGIN;
98b3c16b89Sdan    UPDATE t2 SET c=NULL ORDER BY a, b DESC LIMIT 3 OFFSET 1;
99b3c16b89Sdan    SELECT a, b, c FROM t2;
100b3c16b89Sdan  ROLLBACK;
101b3c16b89Sdan} {
102b3c16b89Sdan  1 1 {}
103b3c16b89Sdan  1 2 g
104b3c16b89Sdan  2 1 {}
105b3c16b89Sdan  2 2 {}
106b3c16b89Sdan  3 1 d
107b3c16b89Sdan  3 2 c
108b3c16b89Sdan  4 1 b
109b3c16b89Sdan  4 2 a
110b3c16b89Sdan}
111b3c16b89Sdan
112ca3e3c3fSdando_execsql_test 2.2.0 {
113ca3e3c3fSdan  DROP TABLE t2;
114ca3e3c3fSdan  CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c) WITHOUT ROWID;
115ca3e3c3fSdan  INSERT INTO t2 VALUES(1, 1, 'h');
116ca3e3c3fSdan  INSERT INTO t2 VALUES(2, 2, 'g');
117ca3e3c3fSdan  INSERT INTO t2 VALUES(3, 1, 'f');
118ca3e3c3fSdan  INSERT INTO t2 VALUES(4, 2, 'e');
119ca3e3c3fSdan  INSERT INTO t2 VALUES(5, 1, 'd');
120ca3e3c3fSdan  INSERT INTO t2 VALUES(6, 2, 'c');
121ca3e3c3fSdan  INSERT INTO t2 VALUES(7, 1, 'b');
122ca3e3c3fSdan  INSERT INTO t2 VALUES(8, 2, 'a');
123ca3e3c3fSdan}
124ca3e3c3fSdan
125ca3e3c3fSdando_execsql_test 2.2.1 {
126ca3e3c3fSdan  BEGIN;
127ca3e3c3fSdan    DELETE FROM t2 WHERE b=1 ORDER BY c LIMIT 2;
128ca3e3c3fSdan    SELECT c FROM t2 ORDER BY 1;
129ca3e3c3fSdan  ROLLBACK;
130ca3e3c3fSdan} {a c e f g h}
131ca3e3c3fSdan
132ca3e3c3fSdando_execsql_test 2.2.2 {
133ca3e3c3fSdan  BEGIN;
134ca3e3c3fSdan    UPDATE t2 SET c=NULL ORDER BY a DESC LIMIT 3 OFFSET 1;
135ca3e3c3fSdan    SELECT a, b, c FROM t2;
136ca3e3c3fSdan  ROLLBACK;
137ca3e3c3fSdan} {
138ca3e3c3fSdan  1 1 h
139ca3e3c3fSdan  2 2 g
140ca3e3c3fSdan  3 1 f
141ca3e3c3fSdan  4 2 e
142ca3e3c3fSdan  5 1 {}
143ca3e3c3fSdan  6 2 {}
144ca3e3c3fSdan  7 1 {}
145ca3e3c3fSdan  8 2 a
146ca3e3c3fSdan}
147ca3e3c3fSdan
14826caf5beSdan#-------------------------------------------------------------------------
14926caf5beSdan# Test using a virtual table
15026caf5beSdan#
15126caf5beSdanifcapable fts5 {
15226caf5beSdan  do_execsql_test 3.0 {
15326caf5beSdan    CREATE VIRTUAL TABLE ft USING fts5(x);
15426caf5beSdan    INSERT INTO ft(rowid, x) VALUES(-45,   'a a');
15526caf5beSdan    INSERT INTO ft(rowid, x) VALUES(12,    'a b');
15626caf5beSdan    INSERT INTO ft(rowid, x) VALUES(444,   'a c');
15726caf5beSdan    INSERT INTO ft(rowid, x) VALUES(12300, 'a d');
15826caf5beSdan    INSERT INTO ft(rowid, x) VALUES(25400, 'a c');
15926caf5beSdan    INSERT INTO ft(rowid, x) VALUES(25401, 'a b');
16026caf5beSdan    INSERT INTO ft(rowid, x) VALUES(50000, 'a a');
16126caf5beSdan  }
16226caf5beSdan
16326caf5beSdan  do_execsql_test 3.1.1 {
16426caf5beSdan    BEGIN;
16526caf5beSdan      DELETE FROM ft ORDER BY rowid LIMIT 3;
16626caf5beSdan      SELECT x FROM ft;
16726caf5beSdan    ROLLBACK;
16826caf5beSdan  } {{a d} {a c} {a b} {a a}}
16926caf5beSdan
17026caf5beSdan  do_execsql_test 3.1.2 {
17126caf5beSdan    BEGIN;
17226caf5beSdan      DELETE FROM ft WHERE ft MATCH 'a' ORDER BY rowid LIMIT 3;
17326caf5beSdan      SELECT x FROM ft;
17426caf5beSdan    ROLLBACK;
17526caf5beSdan  } {{a d} {a c} {a b} {a a}}
17626caf5beSdan
17726caf5beSdan  do_execsql_test 3.1.3 {
17826caf5beSdan    BEGIN;
17926caf5beSdan      DELETE FROM ft WHERE ft MATCH 'b' ORDER BY rowid ASC LIMIT 1 OFFSET 1;
18026caf5beSdan      SELECT rowid FROM ft;
18126caf5beSdan    ROLLBACK;
18226caf5beSdan  } {-45 12 444 12300 25400 50000}
18326caf5beSdan
18426caf5beSdan  do_execsql_test 3.2.1 {
18526caf5beSdan    BEGIN;
18626caf5beSdan      UPDATE ft SET x='hello' ORDER BY rowid LIMIT 2 OFFSET 2;
18726caf5beSdan      SELECT x FROM ft;
18826caf5beSdan    ROLLBACK;
18926caf5beSdan  } {{a a} {a b} hello hello {a c} {a b} {a a}}
19026caf5beSdan
19126caf5beSdan  do_execsql_test 3.2.2 {
19226caf5beSdan    BEGIN;
19326caf5beSdan      UPDATE ft SET x='hello' WHERE ft MATCH 'a'
19426caf5beSdan          ORDER BY rowid DESC LIMIT 2 OFFSET 2;
19526caf5beSdan      SELECT x FROM ft;
19626caf5beSdan    ROLLBACK;
19726caf5beSdan  } {{a a} {a b} {a c} hello hello {a b} {a a}}
19826caf5beSdan} ;# fts5
19926caf5beSdan
20026caf5beSdan#-------------------------------------------------------------------------
20126caf5beSdan# Test using INDEXED BY clauses.
20226caf5beSdan#
203ca3e3c3fSdando_execsql_test 4.0 {
204ca3e3c3fSdan  CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c, d);
20526caf5beSdan  CREATE INDEX x1bc ON x1(b, c);
20626caf5beSdan  INSERT INTO x1 VALUES(1,1,1,1);
20726caf5beSdan  INSERT INTO x1 VALUES(2,1,2,2);
20826caf5beSdan  INSERT INTO x1 VALUES(3,2,1,3);
20926caf5beSdan  INSERT INTO x1 VALUES(4,2,2,3);
21026caf5beSdan  INSERT INTO x1 VALUES(5,3,1,2);
21126caf5beSdan  INSERT INTO x1 VALUES(6,3,2,1);
21226caf5beSdan}
21326caf5beSdan
214ca3e3c3fSdando_execsql_test 4.1 {
21526caf5beSdan  BEGIN;
21626caf5beSdan    DELETE FROM x1 ORDER BY a LIMIT 2;
21726caf5beSdan    SELECT a FROM x1;
21826caf5beSdan  ROLLBACK;
21926caf5beSdan} {3 4 5 6}
22026caf5beSdan
221*51da8dafSdrh# 2020-06-03: Query planner improved so that a solution is possible.
222*51da8dafSdrh#
223*51da8dafSdrh#do_catchsql_test 4.2 {
224*51da8dafSdrh#  DELETE FROM x1 INDEXED BY x1bc WHERE d=3 LIMIT 1;
225*51da8dafSdrh#} {1 {no query solution}}
22626caf5beSdan
227ca3e3c3fSdando_execsql_test 4.3 {
228ca3e3c3fSdan  DELETE FROM x1 INDEXED BY x1bc WHERE b=3 LIMIT 1;
229ca3e3c3fSdan  SELECT a FROM x1;
230ca3e3c3fSdan} {1 2 3 4 6}
23126caf5beSdan
232*51da8dafSdrh# 2020-06-03: Query planner improved so that a solution is possible.
233*51da8dafSdrh#
234*51da8dafSdrh#do_catchsql_test 4.4 {
235*51da8dafSdrh#  UPDATE x1 INDEXED BY x1bc SET d=5 WHERE d=3 LIMIT 1;
236*51da8dafSdrh#} {1 {no query solution}}
237ca3e3c3fSdan
238ca3e3c3fSdando_execsql_test 4.5 {
239ca3e3c3fSdan  UPDATE x1 INDEXED BY x1bc SET d=5 WHERE b=2 LIMIT 1;
240ca3e3c3fSdan  SELECT a, d FROM x1;
241ca3e3c3fSdan} {1 1 2 2 3 5 4 3 6 1}
24226caf5beSdan
24326caf5beSdan#-------------------------------------------------------------------------
24426caf5beSdan# Test using object names that require quoting.
24526caf5beSdan#
246dc32b448Sdando_execsql_test 5.0 {
247dc32b448Sdan  CREATE TABLE "x y"("a b" PRIMARY KEY, "c d") WITHOUT ROWID;
248dc32b448Sdan  CREATE INDEX xycd ON "x y"("c d");
24926caf5beSdan
250dc32b448Sdan  INSERT INTO "x y" VALUES('a', 'a');
251dc32b448Sdan  INSERT INTO "x y" VALUES('b', 'b');
252dc32b448Sdan  INSERT INTO "x y" VALUES('c', 'c');
253dc32b448Sdan  INSERT INTO "x y" VALUES('d', 'd');
254dc32b448Sdan  INSERT INTO "x y" VALUES('e', 'a');
255dc32b448Sdan  INSERT INTO "x y" VALUES('f', 'b');
256dc32b448Sdan  INSERT INTO "x y" VALUES('g', 'c');
257dc32b448Sdan  INSERT INTO "x y" VALUES('h', 'd');
258dc32b448Sdan}
259dc32b448Sdan
260dc32b448Sdando_execsql_test 5.1 {
261dc32b448Sdan  BEGIN;
262dc32b448Sdan    DELETE FROM "x y" WHERE "c d"!='e' ORDER BY "c d" LIMIT 2 OFFSET 2;
263dc32b448Sdan    SELECT * FROM "x y" ORDER BY 1;
264dc32b448Sdan  ROLLBACK;
265dc32b448Sdan} {
266dc32b448Sdan  a a c c d d e a g c h d
267dc32b448Sdan}
268dc32b448Sdan
269dc32b448Sdando_execsql_test 5.2 {
270dc32b448Sdan  BEGIN;
271dc32b448Sdan    UPDATE "x y" SET "c d"='e' WHERE "c d"!='e' ORDER BY "c d" LIMIT 2 OFFSET 2;
272dc32b448Sdan    SELECT * FROM "x y" ORDER BY 1;
273dc32b448Sdan  ROLLBACK;
274dc32b448Sdan} {
275dc32b448Sdan  a a b e c c d d e a f e g c h d
276dc32b448Sdan}
277dc32b448Sdan
278dc32b448Sdanproc log {args} { lappend ::log {*}$args }
279dc32b448Sdandb func log log
280dc32b448Sdando_execsql_test 5.3 {
281dc32b448Sdan  CREATE VIEW "v w" AS SELECT * FROM "x y";
282dc32b448Sdan  CREATE TRIGGER tr1 INSTEAD OF DELETE ON "v w" BEGIN
283dc32b448Sdan    SELECT log(old."a b", old."c d");
284dc32b448Sdan  END;
285dc32b448Sdan  CREATE TRIGGER tr2 INSTEAD OF UPDATE ON "v w" BEGIN
286dc32b448Sdan    SELECT log(new."a b", new."c d");
287dc32b448Sdan  END;
288dc32b448Sdan}
289dc32b448Sdan
290dc32b448Sdando_test 5.4 {
291dc32b448Sdan  set ::log {}
292dc32b448Sdan  execsql { DELETE FROM "v w" ORDER BY "a b" LIMIT 3 }
293dc32b448Sdan  set ::log
294dc32b448Sdan} {a a b b c c}
295dc32b448Sdan
296dc32b448Sdando_test 5.5 {
297dc32b448Sdan  set ::log {}
298dc32b448Sdan  execsql { UPDATE "v w" SET "a b" = "a b" || 'x' ORDER BY "a b" LIMIT 5; }
299dc32b448Sdan  set ::log
300dc32b448Sdan} {ax a bx b cx c dx d ex a}
301b3c16b89Sdan
302b3c16b89Sdan
303b3c16b89Sdanfinish_test
304